remove bytes subproject, add TreeMultiMap
This commit is contained in:
parent
a101c4f4aa
commit
7c925a6357
206 changed files with 71 additions and 33412 deletions
|
@ -1,5 +0,0 @@
|
||||||
This work is derived from
|
|
||||||
|
|
||||||
https://github.com/OpenHFT/Chronicle-Bytes
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0
|
|
|
@ -1,6 +0,0 @@
|
||||||
dependencies {
|
|
||||||
api libs.chronicle.core
|
|
||||||
testImplementation libs.junit.vintage.engine
|
|
||||||
testImplementation libs.junit4
|
|
||||||
testImplementation libs.affinity
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.algo.BytesStoreHash;
|
|
||||||
import net.openhft.chronicle.core.io.AbstractReferenceCounted;
|
|
||||||
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
public abstract class AbstractBytesStore<B extends BytesStore<B, Underlying>, Underlying>
|
|
||||||
extends AbstractReferenceCounted
|
|
||||||
implements BytesStore<B, Underlying> {
|
|
||||||
|
|
||||||
protected AbstractBytesStore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbstractBytesStore(boolean monitored) {
|
|
||||||
super(monitored);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int peekUnsignedByte(long offset) throws BufferUnderflowException {
|
|
||||||
return offset >= readLimit() ? -1 : readUnsignedByte(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return BytesStoreHash.hash32(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readPosition() {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readRemaining() {
|
|
||||||
return readLimit() - readPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long writeRemaining() {
|
|
||||||
return writeLimit() - writePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long start() {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performReleaseInBackground() {
|
|
||||||
return isDirectMemory();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,332 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.annotation.Java9;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UTFDataFormatException;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public enum AppendableUtil {
|
|
||||||
;
|
|
||||||
|
|
||||||
public static void setCharAt( Appendable sb, int index, char ch)
|
|
||||||
throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
if (sb instanceof StringBuilder)
|
|
||||||
((StringBuilder) sb).setCharAt(index, ch);
|
|
||||||
else if (sb instanceof Bytes)
|
|
||||||
((Bytes) sb).writeByte(index, ch);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("" + sb.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parseUtf8( BytesStore bs, StringBuilder sb, boolean utf, int length) throws UTFDataFormatRuntimeException {
|
|
||||||
BytesInternal.parseUtf8(bs, bs.readPosition(), sb, utf, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
public static void setLength( Appendable sb, int newLength)
|
|
||||||
throws BufferUnderflowException, IllegalArgumentException {
|
|
||||||
if (sb instanceof StringBuilder)
|
|
||||||
((StringBuilder) sb).setLength(newLength);
|
|
||||||
else if (sb instanceof Bytes)
|
|
||||||
((Bytes) sb).readPositionRemaining(0, newLength);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("" + sb.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void append( Appendable sb, double value)
|
|
||||||
throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
if (sb instanceof StringBuilder)
|
|
||||||
((StringBuilder) sb).append(value);
|
|
||||||
else if (sb instanceof Bytes)
|
|
||||||
((Bytes) sb).append(value);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("" + sb.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void append( Appendable sb, long value)
|
|
||||||
throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
if (sb instanceof StringBuilder)
|
|
||||||
((StringBuilder) sb).append(value);
|
|
||||||
else if (sb instanceof Bytes)
|
|
||||||
((Bytes) sb).append(value);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("" + sb.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <ACS extends Appendable & CharSequence> void append( ACS sb, String str) {
|
|
||||||
try {
|
|
||||||
sb.append(str);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void read8bitAndAppend( StreamingDataInput bytes,
|
|
||||||
StringBuilder appendable,
|
|
||||||
StopCharsTester tester) {
|
|
||||||
while (true) {
|
|
||||||
int c = bytes.readUnsignedByte();
|
|
||||||
if (tester.isStopChar(c, bytes.peekUnsignedByte()))
|
|
||||||
return;
|
|
||||||
appendable.append((char) c);
|
|
||||||
if (bytes.readRemaining() == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readUTFAndAppend( StreamingDataInput bytes,
|
|
||||||
Appendable appendable,
|
|
||||||
StopCharsTester tester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
readUtf8AndAppend(bytes, appendable, tester);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readUtf8AndAppend( StreamingDataInput bytes,
|
|
||||||
Appendable appendable,
|
|
||||||
StopCharsTester tester)
|
|
||||||
throws BufferUnderflowException, IOException {
|
|
||||||
while (true) {
|
|
||||||
int c = bytes.readUnsignedByte();
|
|
||||||
if (c >= 128) {
|
|
||||||
bytes.readSkip(-1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// this is used for array class such as !type byte[]
|
|
||||||
if (c == '[' && bytes.peekUnsignedByte() == ']') {
|
|
||||||
appendable.append((char) c);
|
|
||||||
appendable.append((char) bytes.readUnsignedByte());
|
|
||||||
if (bytes.readRemaining() == 0)
|
|
||||||
return;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tester.isStopChar(c, bytes.peekUnsignedByte()))
|
|
||||||
return;
|
|
||||||
appendable.append((char) c);
|
|
||||||
if (bytes.readRemaining() == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int c; (c = bytes.readUnsignedByte()) >= 0; ) {
|
|
||||||
switch (c >> 4) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
/* 0xxxxxxx */
|
|
||||||
if (tester.isStopChar(c, bytes.peekUnsignedByte()))
|
|
||||||
return;
|
|
||||||
appendable.append((char) c);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
case 13: {
|
|
||||||
/* 110x xxxx 10xx xxxx */
|
|
||||||
int char2 = bytes.readUnsignedByte();
|
|
||||||
if ((char2 & 0xC0) != 0x80)
|
|
||||||
throw new UTFDataFormatException(
|
|
||||||
"malformed input around byte " + Integer.toHexString(char2));
|
|
||||||
int c2 = (char) (((c & 0x1F) << 6) |
|
|
||||||
(char2 & 0x3F));
|
|
||||||
if (tester.isStopChar(c2, bytes.peekUnsignedByte()))
|
|
||||||
return;
|
|
||||||
appendable.append((char) c2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 14: {
|
|
||||||
/* 1110 xxxx 10xx xxxx 10xx xxxx */
|
|
||||||
int char2 = bytes.readUnsignedByte();
|
|
||||||
int char3 = bytes.readUnsignedByte();
|
|
||||||
|
|
||||||
if (((char2 & 0xC0) != 0x80))
|
|
||||||
throw new UTFDataFormatException(
|
|
||||||
"malformed input around byte " + Integer.toHexString(char2));
|
|
||||||
if ((char3 & 0xC0) != 0x80)
|
|
||||||
throw new UTFDataFormatException(
|
|
||||||
"malformed input around byte " + Integer.toHexString(char3));
|
|
||||||
int c3 = (char) (((c & 0x0F) << 12) |
|
|
||||||
((char2 & 0x3F) << 6) |
|
|
||||||
(char3 & 0x3F));
|
|
||||||
if (tester.isStopChar(c3, bytes.peekUnsignedByte()))
|
|
||||||
return;
|
|
||||||
appendable.append((char) c3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* 10xx xxxx, 1111 xxxx */
|
|
||||||
throw new UTFDataFormatException(
|
|
||||||
"malformed input around byte " + Integer.toHexString(c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parse8bit_SB1( Bytes bytes, StringBuilder sb, int length)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
if (length > bytes.readRemaining())
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
NativeBytesStore nbs = (NativeBytesStore) bytes.bytesStore();
|
|
||||||
long offset = bytes.readPosition();
|
|
||||||
int count = BytesInternal.parse8bit_SB1(offset, nbs, sb, length);
|
|
||||||
bytes.readSkip(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parse8bit( StreamingDataInput bytes, Appendable appendable, int utflen)
|
|
||||||
throws BufferUnderflowException, IOException {
|
|
||||||
if (appendable instanceof StringBuilder) {
|
|
||||||
final StringBuilder sb = (StringBuilder) appendable;
|
|
||||||
if (bytes instanceof Bytes && ((Bytes) bytes).bytesStore() instanceof NativeBytesStore) {
|
|
||||||
parse8bit_SB1((Bytes) bytes, sb, utflen);
|
|
||||||
} else {
|
|
||||||
BytesInternal.parse8bit1(bytes, sb, utflen);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BytesInternal.parse8bit1(bytes, appendable, utflen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <ACS extends Appendable & CharSequence> void append(ACS a, CharSequence cs, long start, long len) {
|
|
||||||
if (a instanceof StringBuilder) {
|
|
||||||
if (cs instanceof Bytes)
|
|
||||||
((StringBuilder) a).append(Bytes.toString(((Bytes) cs), start, len));
|
|
||||||
else
|
|
||||||
((StringBuilder) a).append(cs.subSequence(Maths.toInt32(start), Maths.toInt32(len)));
|
|
||||||
} else if (a instanceof Bytes) {
|
|
||||||
((Bytes) a).appendUtf8(cs, Maths.toInt32(start), Maths.toInt32(len));
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long findUtf8Length( CharSequence str) throws IndexOutOfBoundsException {
|
|
||||||
int strlen = str.length();
|
|
||||||
long utflen = strlen;/* use charAt instead of copying String to char array */
|
|
||||||
for (int i = 0; i < strlen; i++) {
|
|
||||||
char c = str.charAt(i);
|
|
||||||
if (c <= 0x007F) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c <= 0x07FF) {
|
|
||||||
utflen++;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
utflen += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return utflen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Java9
|
|
||||||
public static long findUtf8Length( byte[] bytes, byte coder) {
|
|
||||||
long utflen;
|
|
||||||
|
|
||||||
if (coder == 0) {
|
|
||||||
int strlen = bytes.length;
|
|
||||||
utflen = bytes.length;
|
|
||||||
|
|
||||||
//noinspection ForLoopReplaceableByForEach
|
|
||||||
for (int i = 0; i < strlen; i++) {
|
|
||||||
int b = (bytes[i] & 0xFF);
|
|
||||||
|
|
||||||
if (b > 0x007F) {
|
|
||||||
utflen++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int strlen = bytes.length;
|
|
||||||
utflen = 0;/* use charAt instead of copying String to char array */
|
|
||||||
for (int i = 0; i < strlen; i += 2) {
|
|
||||||
char c = (char) (((bytes[i + 1] & 0xFF) << 8) | (bytes[i] & 0xFF));
|
|
||||||
|
|
||||||
if (c <= 0x007F) {
|
|
||||||
utflen += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c <= 0x07FF) {
|
|
||||||
utflen += 2;
|
|
||||||
} else {
|
|
||||||
utflen += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return utflen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Java9
|
|
||||||
public static long findUtf8Length( byte[] chars) {
|
|
||||||
long utflen = 0; /* use charAt instead of copying String to char array */
|
|
||||||
int strlen = chars.length;
|
|
||||||
for (int i = 0; i < strlen; i++) {
|
|
||||||
int c = chars[i] & 0xFF; // unsigned byte
|
|
||||||
|
|
||||||
if (c == 0) { // we have hit end of string
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c >= 0xF0) {
|
|
||||||
utflen += 4;
|
|
||||||
i += 3;
|
|
||||||
} else if (c >= 0xE0) {
|
|
||||||
utflen += 3;
|
|
||||||
i += 2;
|
|
||||||
} else if (c >= 0xC0) {
|
|
||||||
utflen += 2;
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
utflen += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return utflen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long findUtf8Length( char[] chars) {
|
|
||||||
long utflen = chars.length;/* use charAt instead of copying String to char array */
|
|
||||||
for (char c : chars) {
|
|
||||||
if (c <= 0x007F) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c <= 0x07FF) {
|
|
||||||
utflen++;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
utflen += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return utflen;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.util.AbstractInvocationHandler;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class BinaryBytesMethodWriterInvocationHandler extends AbstractInvocationHandler implements BytesMethodWriterInvocationHandler {
|
|
||||||
private final Function<Method, MethodEncoder> methodToId;
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final BytesOut out;
|
|
||||||
private final Map<Method, MethodEncoder> methodToIdMap = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public BinaryBytesMethodWriterInvocationHandler(Function<Method, MethodEncoder> methodToId, BytesOut out) {
|
|
||||||
super(HashMap::new);
|
|
||||||
this.methodToId = methodToId;
|
|
||||||
this.out = out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object doInvoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
|
|
||||||
MethodEncoder info = methodToIdMap.computeIfAbsent(method, methodToId);
|
|
||||||
if (info == null) {
|
|
||||||
Jvm.warn().on(getClass(), "Unknown method " + method + " ignored");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
out.comment(method.getName());
|
|
||||||
out.writeStopBit(info.messageId());
|
|
||||||
info.encode(args, out);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
public interface BinaryWireCode {
|
|
||||||
|
|
||||||
// sequence of length 0 - 255 bytes
|
|
||||||
int BYTES_LENGTH8 = 0x80;
|
|
||||||
// sequence of length 0 - 2^16-1 bytes
|
|
||||||
int BYTES_LENGTH16 = 0x81;
|
|
||||||
// sequence of length 0 - 2^32-1
|
|
||||||
int BYTES_LENGTH32 = 0x82;
|
|
||||||
// sequence of length 0 - 255
|
|
||||||
// public static final int BYTES_LENGTH64 = 0x83;
|
|
||||||
|
|
||||||
int FIELD_ANCHOR = 0x87;
|
|
||||||
int ANCHOR = 0x88;
|
|
||||||
int UPDATED_ALIAS = 0x89;
|
|
||||||
|
|
||||||
// an array of unsigned bytes
|
|
||||||
int U8_ARRAY = 0x8A;
|
|
||||||
// public static final int U16_ARRAY = 0x8B;
|
|
||||||
// public static final int I32_ARRAY = 0x8C;
|
|
||||||
int I64_ARRAY = 0x8D;
|
|
||||||
int PADDING32 = 0x8E;
|
|
||||||
int PADDING = 0x8F;
|
|
||||||
|
|
||||||
int FLOAT32 = 0x90;
|
|
||||||
int FLOAT64 = 0x91;
|
|
||||||
int FLOAT_STOP_2 = 0x92;
|
|
||||||
int FLOAT_STOP_4 = 0x94;
|
|
||||||
int FLOAT_STOP_6 = 0x96;
|
|
||||||
int FLOAT_SET_LOW_0 = 0x9A;
|
|
||||||
int FLOAT_SET_LOW_2 = 0x9B;
|
|
||||||
int FLOAT_SET_LOW_4 = 0x9C;
|
|
||||||
// 0x98 - 0x9F
|
|
||||||
|
|
||||||
int UUID = 0xA0;
|
|
||||||
int UINT8 = 0xA1;
|
|
||||||
int UINT16 = 0xA2;
|
|
||||||
int UINT32 = 0xA3;
|
|
||||||
int INT8 = 0xA4;
|
|
||||||
int INT16 = 0xA5;
|
|
||||||
int INT32 = 0xA6;
|
|
||||||
int INT64 = 0xA7;
|
|
||||||
int SET_LOW_INT8 = 0xA8;
|
|
||||||
int SET_LOW_INT16 = 0xA9;
|
|
||||||
// public static final int FIXED_5 = 0xAA;
|
|
||||||
// public static final int FIXED_4 = 0xAB;
|
|
||||||
// public static final int FIXED_3 = 0xAC;
|
|
||||||
// public static final int FIXED_2 = 0xAD;
|
|
||||||
int STOP_BIT = 0xAE;
|
|
||||||
int INT64_0x = 0xAF;
|
|
||||||
|
|
||||||
int FALSE = 0xB0;
|
|
||||||
int TRUE = 0xB1;
|
|
||||||
int TIME = 0xB2;
|
|
||||||
int DATE = 0xB3;
|
|
||||||
int DATE_TIME = 0xB4;
|
|
||||||
int ZONED_DATE_TIME = 0xB5;
|
|
||||||
int TYPE_PREFIX = 0xB6;
|
|
||||||
int FIELD_NAME_ANY = 0xB7;
|
|
||||||
int STRING_ANY = 0xB8;
|
|
||||||
int EVENT_NAME = 0xB9;
|
|
||||||
int FIELD_NUMBER = 0xBA;
|
|
||||||
int NULL = 0xBB;
|
|
||||||
int TYPE_LITERAL = 0xBC;
|
|
||||||
int EVENT_OBJECT = 0xBD;
|
|
||||||
int COMMENT = 0xBE;
|
|
||||||
int HINT = 0xBF;
|
|
||||||
|
|
||||||
int FIELD_NAME0 = 0xC0;
|
|
||||||
// ...
|
|
||||||
int FIELD_NAME31 = 0xDF;
|
|
||||||
|
|
||||||
int STRING_0 = 0xE0;
|
|
||||||
// ...
|
|
||||||
int STRING_31 = 0xFF;
|
|
||||||
|
|
||||||
String[] STRING_FOR_CODE = _stringForCode(BinaryWireCode.class);
|
|
||||||
|
|
||||||
static String[] _stringForCode(Class clazz) {
|
|
||||||
String[] stringForCode = new String[256];
|
|
||||||
try {
|
|
||||||
for ( Field field : clazz.getDeclaredFields()) {
|
|
||||||
if (field.getType() == int.class)
|
|
||||||
stringForCode[field.getInt(null)] = field.getName();
|
|
||||||
else if (field.getType() == byte.class)
|
|
||||||
stringForCode[field.getByte(null) & 0xFF] = field.getName();
|
|
||||||
}
|
|
||||||
for (int i = FIELD_NAME0; i <= FIELD_NAME31; i++)
|
|
||||||
stringForCode[i] = "FIELD_" + i;
|
|
||||||
for (int i = STRING_0; i <= STRING_31; i++)
|
|
||||||
stringForCode[i] = "STRING_" + i;
|
|
||||||
for (int i = 0; i < stringForCode.length; i++) {
|
|
||||||
if (stringForCode[i] == null)
|
|
||||||
if (i <= ' ' || i >= 127)
|
|
||||||
stringForCode[i] = "Unknown_0x" + Integer.toHexString(i).toUpperCase();
|
|
||||||
else
|
|
||||||
stringForCode[i] = "Unknown_" + (char) i;
|
|
||||||
}
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return stringForCode;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,308 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.UnsafeText;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Methods to append text to a Bytes. This extends the Appendable interface.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface ByteStringAppender<B extends ByteStringAppender<B>> extends StreamingDataOutput<B>, Appendable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return these Bytes as a Writer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default Writer writer() {
|
|
||||||
return new ByteStringWriter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a char in UTF-8
|
|
||||||
*
|
|
||||||
* @param ch to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default B append(char ch) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendUtf8Char(this, ch);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a characters in UTF-8
|
|
||||||
*
|
|
||||||
* @param cs to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default B append( CharSequence cs) throws BufferOverflowException {
|
|
||||||
if (cs.length() == 0)
|
|
||||||
return (B) this;
|
|
||||||
try {
|
|
||||||
return append(cs, 0, cs.length());
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a boolean as T or F
|
|
||||||
*
|
|
||||||
* @param flag to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(boolean flag) throws BufferOverflowException {
|
|
||||||
return append(flag ? 'T' : 'F');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append an int in decimal
|
|
||||||
*
|
|
||||||
* @param value to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(int value) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendBase10(this, value);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a long in decimal
|
|
||||||
*
|
|
||||||
* @param value to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(long value) throws BufferOverflowException {
|
|
||||||
if (value == (int) value)
|
|
||||||
BytesInternal.appendBase10(this, (int) value);
|
|
||||||
else
|
|
||||||
BytesInternal.appendBase10(this, value);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B appendBase(long value, int base) throws BufferOverflowException {
|
|
||||||
BytesInternal.append(this, value, base);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B appendBase16(long value) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendBase16(this, value, 1);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B appendBase16(long value, int minDigits) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendBase16(this, value, minDigits);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a long in decimal with a given number of decimal places. Print value * 10^-decimalPlaces
|
|
||||||
*
|
|
||||||
* @param value to append
|
|
||||||
* @param decimalPlaces to shift the decimal place.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B appendDecimal(long value, int decimalPlaces) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendDecimal(this, value, decimalPlaces);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a float in decimal notation
|
|
||||||
*
|
|
||||||
* @param f to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(float f) throws BufferOverflowException {
|
|
||||||
float f2 = Math.abs(f);
|
|
||||||
if (f2 > 1e6 || f2 < 1e-3) {
|
|
||||||
return append(Float.toString(f));
|
|
||||||
}
|
|
||||||
int precision = (int) Math.floor(6 - Math.log10(f2));
|
|
||||||
long tens = Maths.tens(precision);
|
|
||||||
return append((double) Math.round(f * tens) / tens);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a double in decimal notation
|
|
||||||
*
|
|
||||||
* @param d to append
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(double d) throws BufferOverflowException {
|
|
||||||
BytesInternal.append(this, d);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a double in decimal notation to a specific number of decimal places. Trailing zeros are not truncated.
|
|
||||||
* <p>
|
|
||||||
* If the number would normally be printed with more decimal places, the number is rounded.
|
|
||||||
*
|
|
||||||
* @param d to append
|
|
||||||
* @param decimalPlaces to always produce
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append(double d, int decimalPlaces) throws BufferOverflowException {
|
|
||||||
if (decimalPlaces < 0)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
if (decimalPlaces < 18) {
|
|
||||||
double d2 = d * Maths.tens(decimalPlaces);
|
|
||||||
if (d2 < Long.MAX_VALUE && d2 > Long.MIN_VALUE) {
|
|
||||||
// changed from java.lang.Math.round(d2) as this was shown up to cause latency
|
|
||||||
long round = d2 > 0.0 ? (long) (d2 + 0.5) : (long) (d2 - 0.5);
|
|
||||||
if (canWriteDirect(20 + decimalPlaces)) {
|
|
||||||
long address = addressForWritePosition();
|
|
||||||
long address2 = UnsafeText.appendBase10d(address, round, decimalPlaces);
|
|
||||||
writeSkip(address2 - address);
|
|
||||||
} else {
|
|
||||||
appendDecimal(round, decimalPlaces);
|
|
||||||
}
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return append(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a portion of a String to the Bytes in UTF-8.
|
|
||||||
*
|
|
||||||
* @param cs to copy
|
|
||||||
* @param start index of the first char inclusive
|
|
||||||
* @param end index of the last char exclusive.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default B append( CharSequence cs, int start, int end)
|
|
||||||
throws IndexOutOfBoundsException, BufferOverflowException {
|
|
||||||
BytesInternal.appendUtf8(this, cs, start, end - start);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a String to the Bytes in ISO-8859-1
|
|
||||||
*
|
|
||||||
* @param cs to write
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException If the string as too large to write in the capacity available
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
default B append8bit( CharSequence cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
return append8bit(cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
default B append8bit( BytesStore bs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
return write(bs, 0L, bs.readRemaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
default B append8bit( String cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
return append8bit(cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a portion of a String to the Bytes in ISO-8859-1
|
|
||||||
*
|
|
||||||
* @param cs to copy
|
|
||||||
* @param start index of the first char inclusive
|
|
||||||
* @param end index of the last char exclusive.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException If the string as too large to write in the capacity available
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IndexOutOfBoundsException if the start or the end are not valid for the CharSequence
|
|
||||||
*/
|
|
||||||
default B append8bit( CharSequence cs, int start, int end)
|
|
||||||
throws IllegalArgumentException, BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
if (cs instanceof BytesStore) {
|
|
||||||
return write((BytesStore) cs, (long) start, end);
|
|
||||||
}
|
|
||||||
for (int i = start; i < end; i++) {
|
|
||||||
char c = cs.charAt(i);
|
|
||||||
if (c > 255) c = '?';
|
|
||||||
writeByte((byte) c);
|
|
||||||
}
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
default B append8bit( BytesStore bs, long start, long end)
|
|
||||||
throws IllegalArgumentException, BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
return write(bs, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B appendDateMillis(long dateInMillis) {
|
|
||||||
BytesInternal.appendDateMillis(this, dateInMillis);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B appendTimeMillis(long timeOfDayInMillis) {
|
|
||||||
BytesInternal.appendTimeMillis(this, timeOfDayInMillis % 86400_000L);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default B append( BigDecimal bigDecimal) {
|
|
||||||
append(bigDecimal.toString());
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,252 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Supports parsing bytes as text. You can parse them as special or white space terminated text.
|
|
||||||
*/
|
|
||||||
interface ByteStringParser<B extends ByteStringParser<B>> extends StreamingDataInput<B> {
|
|
||||||
/**
|
|
||||||
* Access these bytes as an ISO-8859-1 encoded Reader
|
|
||||||
*
|
|
||||||
* @return as a Reader
|
|
||||||
*/
|
|
||||||
|
|
||||||
default Reader reader() {
|
|
||||||
return new ByteStringReader(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true or false, or null if it could not be detected
|
|
||||||
* as true or false. Case is not important
|
|
||||||
* <p>
|
|
||||||
* <p>false: f, false, n, no, 0
|
|
||||||
* <p>
|
|
||||||
* <p>true: t, true, y, yes, 1
|
|
||||||
*
|
|
||||||
* @param tester to detect the end of the text.
|
|
||||||
* @return true, false, or null if neither.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default Boolean parseBoolean( StopCharTester tester) {
|
|
||||||
return BytesInternal.parseBoolean(this, tester);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default Boolean parseBoolean() {
|
|
||||||
return BytesInternal.parseBoolean(this, StopCharTesters.NON_ALPHA_DIGIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with UTF-8 decoding as character terminated.
|
|
||||||
*
|
|
||||||
* @param stopCharTester to check if the end has been reached.
|
|
||||||
* @return the text as a String.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
default String parseUtf8( StopCharTester stopCharTester) {
|
|
||||||
return BytesInternal.parseUtf8(this, stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default String parseUTF( StopCharTester stopCharTester) {
|
|
||||||
return parseUtf8(stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with UTF-8 decoding as character terminated.
|
|
||||||
*
|
|
||||||
* @param buffer to populate
|
|
||||||
* @param stopCharTester to check if the end has been reached.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default void parseUtf8( Appendable buffer, StopCharTester stopCharTester) throws BufferUnderflowException {
|
|
||||||
BytesInternal.parseUtf8(this, buffer, stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default void parseUTF( Appendable buffer, StopCharTester stopCharTester) throws BufferUnderflowException {
|
|
||||||
parseUtf8(buffer, stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with UTF-8 decoding as one or two character terminated.
|
|
||||||
*
|
|
||||||
* @param buffer to populate
|
|
||||||
* @param stopCharsTester to check if the end has been reached.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default void parseUtf8( Appendable buffer, StopCharsTester stopCharsTester)
|
|
||||||
throws BufferUnderflowException, IORuntimeException {
|
|
||||||
BytesInternal.parseUtf8(this, buffer, stopCharsTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default void parseUTF( Appendable buffer, StopCharsTester stopCharsTester)
|
|
||||||
throws BufferUnderflowException, IORuntimeException {
|
|
||||||
parseUtf8(buffer, stopCharsTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with ISO-8859-1 decoding as character terminated.
|
|
||||||
*
|
|
||||||
* @param buffer to populate
|
|
||||||
* @param stopCharTester to check if the end has been reached.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@ForceInline
|
|
||||||
default void parse8bit(Appendable buffer, StopCharTester stopCharTester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
if (buffer instanceof StringBuilder)
|
|
||||||
BytesInternal.parse8bit(this, (StringBuilder) buffer, stopCharTester);
|
|
||||||
else
|
|
||||||
BytesInternal.parse8bit(this, (Bytes) buffer, stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with ISO-8859-1 decoding as character terminated.
|
|
||||||
*
|
|
||||||
* @param stopCharTester to check if the end has been reached.
|
|
||||||
*/
|
|
||||||
default String parse8bit( StopCharTester stopCharTester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesInternal.parse8bit(this, stopCharTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text with ISO-8859-1 decoding as character terminated.
|
|
||||||
*
|
|
||||||
* @param buffer to populate
|
|
||||||
* @param stopCharsTester to check if the end has been reached.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@ForceInline
|
|
||||||
default void parse8bit(Appendable buffer, StopCharsTester stopCharsTester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
if (buffer instanceof StringBuilder)
|
|
||||||
BytesInternal.parse8bit(this, (StringBuilder) buffer, stopCharsTester);
|
|
||||||
else
|
|
||||||
BytesInternal.parse8bit(this, (Bytes) buffer, stopCharsTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
default void parse8bit(Bytes buffer, StopCharsTester stopCharsTester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
BytesInternal.parse8bit(this, buffer, stopCharsTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void parse8bit(StringBuilder buffer, StopCharsTester stopCharsTester)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
BytesInternal.parse8bit(this, buffer, stopCharsTester);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text as an int. The terminating character is consumed.
|
|
||||||
*
|
|
||||||
* @return an int.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default int parseInt() throws BufferUnderflowException {
|
|
||||||
return Maths.toInt32(BytesInternal.parseLong(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text as a long integer. The terminating character is consumed.
|
|
||||||
*
|
|
||||||
* @return a long.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long parseLong() throws BufferUnderflowException {
|
|
||||||
return BytesInternal.parseLong(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text as a float decimal. The terminating character is consumed.
|
|
||||||
* <p>
|
|
||||||
* The number of decimal places can be retrieved with lastDecimalPlaces()
|
|
||||||
*
|
|
||||||
* @return a float.
|
|
||||||
*/
|
|
||||||
default float parseFloat() throws BufferUnderflowException {
|
|
||||||
return (float) BytesInternal.parseDouble(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parse text as a double decimal. The terminating character is consumed.
|
|
||||||
* <p>
|
|
||||||
* The number of decimal places can be retrieved with lastDecimalPlaces()
|
|
||||||
*
|
|
||||||
* @return a double.
|
|
||||||
*/
|
|
||||||
default double parseDouble() throws BufferUnderflowException {
|
|
||||||
return BytesInternal.parseDouble(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the significant digits of a decimal number.
|
|
||||||
* <p>
|
|
||||||
* The number of decimal places can be retrieved with lastDecimalPlaces()
|
|
||||||
*
|
|
||||||
* @return the significant digits
|
|
||||||
*/
|
|
||||||
default long parseLongDecimal() throws BufferUnderflowException {
|
|
||||||
return BytesInternal.parseLongDecimal(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the last number of decimal places for parseDouble or parseLongDecimal
|
|
||||||
*/
|
|
||||||
int lastDecimalPlaces();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store the last number of decimal places. If
|
|
||||||
*
|
|
||||||
* @param lastDecimalPlaces set the number of decimal places if positive, otherwise 0.
|
|
||||||
*/
|
|
||||||
void lastDecimalPlaces(int lastDecimalPlaces);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip text until a terminating character is reached.
|
|
||||||
*
|
|
||||||
* @param tester to stop at
|
|
||||||
* @return true if a terminating character was found, false if the end of the buffer was reached.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default boolean skipTo( StopCharTester tester) {
|
|
||||||
return BytesInternal.skipTo(this, tester);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default BigDecimal parseBigDecimal() {
|
|
||||||
return new BigDecimal(parseUtf8(StopCharTesters.NUMBER_END));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Reader wrapper for Bytes. This Reader moves the readPosition() of the underlying Bytes up to the readLimit()
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class ByteStringReader extends Reader {
|
|
||||||
private final ByteStringParser in;
|
|
||||||
|
|
||||||
public ByteStringReader(ByteStringParser in) {
|
|
||||||
this.in = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() {
|
|
||||||
return in.readRemaining() > 0 ? in.readUnsignedByte() : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long skip(long n) throws IOException {
|
|
||||||
long len = Math.min(in.readRemaining(), n);
|
|
||||||
try {
|
|
||||||
in.readSkip(len);
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
|
||||||
try {
|
|
||||||
return in.read(cbuf, off, len);
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Writer for an underlying Bytes. This moves the writePosition() up to the writeLimit();
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
class ByteStringWriter extends Writer {
|
|
||||||
private final ByteStringAppender out;
|
|
||||||
|
|
||||||
ByteStringWriter(ByteStringAppender out) {
|
|
||||||
this.out = out;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(int c) throws IOException {
|
|
||||||
try {
|
|
||||||
out.append((char) c);
|
|
||||||
|
|
||||||
} catch ( BufferOverflowException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write( String str) throws IOException {
|
|
||||||
out.append(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write( String str, int off, int len) throws IOException {
|
|
||||||
out.append(str, off, off + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Writer append( CharSequence csq) throws IOException {
|
|
||||||
out.append(csq);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Writer append( CharSequence csq, int start, int end) throws IOException {
|
|
||||||
out.append(csq, start, end);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Writer append(char c) throws IOException {
|
|
||||||
out.append(c);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
out.append(cbuf[i + off]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This Interface allows a reference to off heap memory to be reassigned.
|
|
||||||
* <p></p>
|
|
||||||
* A reference to off heap memory is a proxy for some memory which sits outside the heap.
|
|
||||||
*/
|
|
||||||
public interface Byteable<B extends BytesStore<B, Underlying>, Underlying> {
|
|
||||||
/**
|
|
||||||
* This setter for a data type which points to an underlying ByteStore.
|
|
||||||
*
|
|
||||||
* @param bytesStore the fix point ByteStore
|
|
||||||
* @param offset the offset within the ByteStore
|
|
||||||
* @param length the length in the ByteStore
|
|
||||||
*/
|
|
||||||
void bytesStore(BytesStore<B, Underlying> bytesStore, long offset, long length)
|
|
||||||
throws IllegalStateException, IllegalArgumentException, BufferOverflowException,
|
|
||||||
BufferUnderflowException;
|
|
||||||
|
|
||||||
|
|
||||||
BytesStore<B, Underlying> bytesStore();
|
|
||||||
|
|
||||||
long offset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the maximum size in byte for this reference.
|
|
||||||
*/
|
|
||||||
long maxSize();
|
|
||||||
}
|
|
|
@ -1,944 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.annotation.UsedViaReflection;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import net.openhft.chronicle.core.util.ObjectUtils;
|
|
||||||
import net.openhft.chronicle.core.util.StringUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bytes is a pointer to a region of memory within a BytesStore. It can be for a fixed region of
|
|
||||||
* memory or an "elastic" buffer which can be resized, but not for a fixed region. <p></p> This is a
|
|
||||||
* BytesStore which is mutable and not thread safe. It has a write position and read position which
|
|
||||||
* must follow these constraints <p></p> start() <= readPosition() <= writePosition() <=
|
|
||||||
* writeLimit() <= capacity() <p></p> Also readLimit() == writePosition() and readPosition()
|
|
||||||
* <= safeLimit(); <p></p>
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface Bytes<Underlying> extends
|
|
||||||
BytesStore<Bytes<Underlying>, Underlying>,
|
|
||||||
BytesIn<Underlying>,
|
|
||||||
BytesOut<Underlying> {
|
|
||||||
|
|
||||||
long MAX_CAPACITY = Long.MAX_VALUE & ~0xF; // 8 EiB - 16
|
|
||||||
int MAX_HEAP_CAPACITY = Integer.MAX_VALUE & ~0xF; // 2 GiB - 16
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
int MAX_BYTE_BUFFER_CAPACITY = MAX_HEAP_CAPACITY;
|
|
||||||
int DEFAULT_BYTE_BUFFER_CAPACITY = 256;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for a direct (off-heap) ByteBuffer with a default capacity
|
|
||||||
* which will be resized as required.
|
|
||||||
*
|
|
||||||
* @return a new elastic wrapper for a direct (off-heap) ByteBuffer with a default capacity
|
|
||||||
* which will be resized as required
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> elasticByteBuffer() {
|
|
||||||
return elasticByteBuffer(DEFAULT_BYTE_BUFFER_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for a direct (off-heap) ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required.
|
|
||||||
*
|
|
||||||
* @param initialCapacity the initial non-negative capacity given in bytes
|
|
||||||
* @return a new elastic wrapper for a direct (off-heap) ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> elasticByteBuffer(int initialCapacity) {
|
|
||||||
return elasticByteBuffer(initialCapacity, MAX_HEAP_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for a direct (off-heap) ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required up
|
|
||||||
* to the given {@code maxSize}.
|
|
||||||
*
|
|
||||||
* @param initialCapacity the initial non-negative capacity given in bytes
|
|
||||||
* @param maxCapacity the max capacity given in bytes equal or greater than initialCapacity
|
|
||||||
* @return a new elastic wrapper for a direct (off-heap) ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required up
|
|
||||||
* to the given {@code maxCapacity}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> elasticByteBuffer(int initialCapacity, int maxCapacity) {
|
|
||||||
NativeBytesStore<ByteBuffer> bs = NativeBytesStore.elasticByteBuffer(initialCapacity, maxCapacity);
|
|
||||||
try {
|
|
||||||
return bs.bytesForWrite();
|
|
||||||
} finally {
|
|
||||||
bs.release(ReferenceOwner.INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for a heap ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required.
|
|
||||||
*
|
|
||||||
* @param initialCapacity the initial non-negative capacity given in bytes
|
|
||||||
* @return a new elastic wrapper for a heap ByteBuffer with
|
|
||||||
* the given {@code initialCapacity} which will be resized as required
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> elasticHeapByteBuffer(int initialCapacity) {
|
|
||||||
HeapBytesStore<ByteBuffer> bs = HeapBytesStore.wrap(ByteBuffer.allocate(initialCapacity));
|
|
||||||
try {
|
|
||||||
return NativeBytes.wrapWithNativeBytes(bs, Bytes.MAX_HEAP_CAPACITY);
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> elasticHeapByteBuffer() {
|
|
||||||
return elasticHeapByteBuffer(128);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the ByteBuffer ready for reading
|
|
||||||
* Method for convenience only - might not be ideal for performance (creates garbage).
|
|
||||||
* To avoid garbage, use something like this example:
|
|
||||||
* <pre>{@code
|
|
||||||
* import net.openhft.chronicle.bytes.Bytes;
|
|
||||||
* import java.nio.ByteBuffer;
|
|
||||||
*
|
|
||||||
* public class ChronicleBytesWithByteBufferExampleTest {
|
|
||||||
* private static final String HELLO_WORLD = "hello world";
|
|
||||||
*
|
|
||||||
* public static void main(String[] args) throws InterruptedException {
|
|
||||||
* //setup Bytes and ByteBuffer to write from
|
|
||||||
* Bytes b = Bytes.elasticByteBuffer();
|
|
||||||
* ByteBuffer toWriteFrom = ByteBuffer.allocate(HELLO_WORLD.length());
|
|
||||||
* toWriteFrom.put(HELLO_WORLD.getBytes(), 0, HELLO_WORLD.length());
|
|
||||||
* toWriteFrom.flip();
|
|
||||||
* byte[] toReadTo = new byte[HELLO_WORLD.length()];
|
|
||||||
*
|
|
||||||
* doWrite(b, toWriteFrom);
|
|
||||||
* ByteBuffer byteBuffer = doRead(b);
|
|
||||||
*
|
|
||||||
* //check result
|
|
||||||
* final StringBuilder sb = new StringBuilder();
|
|
||||||
* for (int i = 0; i < HELLO_WORLD.length(); i++) {
|
|
||||||
* sb.append((char) byteBuffer.get());
|
|
||||||
* }
|
|
||||||
* assert sb.toString().equals(HELLO_WORLD): "Failed - strings not equal!";
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doWrite(Bytes b, ByteBuffer toWrite) {
|
|
||||||
* //no garbage when writing to Bytes from ByteBuffer
|
|
||||||
* b.clear();
|
|
||||||
* b.write(b.writePosition(), toWrite, toWrite.position(), toWrite.limit());
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static ByteBuffer doRead(Bytes b) {
|
|
||||||
* //no garbage when getting the underlying ByteBuffer
|
|
||||||
* assert b.underlyingObject() instanceof ByteBuffer;
|
|
||||||
* ByteBuffer byteBuffer = (ByteBuffer) b.underlyingObject();
|
|
||||||
* return byteBuffer;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param byteBuffer to wrap
|
|
||||||
* @return a Bytes which wraps the provided ByteBuffer and is ready for reading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> wrapForRead( ByteBuffer byteBuffer) {
|
|
||||||
BytesStore<?, ByteBuffer> bs = BytesStore.wrap(byteBuffer);
|
|
||||||
try {
|
|
||||||
Bytes<ByteBuffer> bbb = bs.bytesForRead();
|
|
||||||
bbb.readLimit(byteBuffer.limit());
|
|
||||||
bbb.readPosition(byteBuffer.position());
|
|
||||||
return bbb;
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the ByteBuffer ready for writing
|
|
||||||
* Method for convenience only - might not be ideal for performance (creates garbage).
|
|
||||||
* To avoid garbage, use something like this example:
|
|
||||||
* <pre>{@code
|
|
||||||
* import net.openhft.chronicle.bytes.Bytes;
|
|
||||||
* import java.nio.ByteBuffer;
|
|
||||||
*
|
|
||||||
* public class ChronicleBytesWithByteBufferExampleTest {
|
|
||||||
* private static final String HELLO_WORLD = "hello world";
|
|
||||||
*
|
|
||||||
* public static void main(String[] args) throws InterruptedException {
|
|
||||||
* //setup Bytes and ByteBuffer to write from
|
|
||||||
* Bytes b = Bytes.elasticByteBuffer();
|
|
||||||
* ByteBuffer toWriteFrom = ByteBuffer.allocate(HELLO_WORLD.length());
|
|
||||||
* toWriteFrom.put(HELLO_WORLD.getBytes(), 0, HELLO_WORLD.length());
|
|
||||||
* toWriteFrom.flip();
|
|
||||||
* byte[] toReadTo = new byte[HELLO_WORLD.length()];
|
|
||||||
*
|
|
||||||
* doWrite(b, toWriteFrom);
|
|
||||||
* ByteBuffer byteBuffer = doRead(b);
|
|
||||||
*
|
|
||||||
* //check result
|
|
||||||
* final StringBuilder sb = new StringBuilder();
|
|
||||||
* for (int i = 0; i < HELLO_WORLD.length(); i++) {
|
|
||||||
* sb.append((char) byteBuffer.get());
|
|
||||||
* }
|
|
||||||
* assert sb.toString().equals(HELLO_WORLD): "Failed - strings not equal!";
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doWrite(Bytes b, ByteBuffer toWrite) {
|
|
||||||
* //no garbage when writing to Bytes from ByteBuffer
|
|
||||||
* b.clear();
|
|
||||||
* b.write(b.writePosition(), toWrite, toWrite.position(), toWrite.limit());
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static ByteBuffer doRead(Bytes b) {
|
|
||||||
* //no garbage when getting the underlying ByteBuffer
|
|
||||||
* assert b.underlyingObject() instanceof ByteBuffer;
|
|
||||||
* ByteBuffer byteBuffer = (ByteBuffer) b.underlyingObject();
|
|
||||||
* return byteBuffer;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param byteBuffer to wrap
|
|
||||||
* @return a Bytes which wraps the provided ByteBuffer and is ready for writing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<ByteBuffer> wrapForWrite( ByteBuffer byteBuffer) {
|
|
||||||
BytesStore<?, ByteBuffer> bs = BytesStore.wrap(byteBuffer);
|
|
||||||
try {
|
|
||||||
Bytes<ByteBuffer> bbb = bs.bytesForWrite();
|
|
||||||
bbb.writePosition(byteBuffer.position());
|
|
||||||
bbb.writeLimit(byteBuffer.limit());
|
|
||||||
return bbb;
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the byte[] ready for reading
|
|
||||||
* Method for convenience only - might not be ideal for performance (creates garbage).
|
|
||||||
* To avoid garbage, use something like this example:
|
|
||||||
* <pre>{@code
|
|
||||||
* import net.openhft.chronicle.bytes.Bytes;
|
|
||||||
* import java.nio.charset.Charset;
|
|
||||||
*
|
|
||||||
* public class ChronicleBytesWithPrimByteArrayExampleTest {
|
|
||||||
* private static final Charset ISO_8859 = Charset.forName("ISO-8859-1");
|
|
||||||
* private static final String HELLO_WORLD = "hello world";
|
|
||||||
*
|
|
||||||
* public static void main(String[] args) {
|
|
||||||
* //setup Bytes and byte[]s to write from and read to
|
|
||||||
* Bytes b = Bytes.elasticByteBuffer();
|
|
||||||
* byte[] toWriteFrom = HELLO_WORLD.getBytes(ISO_8859);
|
|
||||||
* byte[] toReadTo = new byte[HELLO_WORLD.length()];
|
|
||||||
*
|
|
||||||
* doWrite(b, toWriteFrom);
|
|
||||||
* doRead(b, toReadTo);
|
|
||||||
*
|
|
||||||
* //check result
|
|
||||||
* final StringBuilder sb = new StringBuilder();
|
|
||||||
* for (int i = 0; i < HELLO_WORLD.length(); i++) {
|
|
||||||
* sb.append((char) toReadTo[i]);
|
|
||||||
* }
|
|
||||||
* assert sb.toString().equals(HELLO_WORLD): "Failed - strings not equal!";
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doWrite(Bytes b, byte[] toWrite) {
|
|
||||||
* //no garbage when writing to Bytes from byte[]
|
|
||||||
* b.clear();
|
|
||||||
* b.write(toWrite);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doRead(Bytes b, byte[] toReadTo) {
|
|
||||||
* //no garbage when reading from Bytes into byte[]
|
|
||||||
* b.read( toReadTo, 0, HELLO_WORLD.length());
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param byteArray to wrap
|
|
||||||
* @return the Bytes ready for reading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<byte[]> wrapForRead( byte[] byteArray) {
|
|
||||||
HeapBytesStore<byte[]> bs = BytesStore.wrap(byteArray);
|
|
||||||
try {
|
|
||||||
return bs.bytesForRead();
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the byte[] ready for writing
|
|
||||||
* Method for convenience only - might not be ideal for performance (creates garbage).
|
|
||||||
* To avoid garbage, use something like this example:
|
|
||||||
* <pre>{@code
|
|
||||||
* import net.openhft.chronicle.bytes.Bytes;
|
|
||||||
* import java.nio.charset.Charset;
|
|
||||||
*
|
|
||||||
* public class ChronicleBytesWithPrimByteArrayExampleTest {
|
|
||||||
* private static final Charset ISO_8859 = Charset.forName("ISO-8859-1");
|
|
||||||
* private static final String HELLO_WORLD = "hello world";
|
|
||||||
*
|
|
||||||
* public static void main(String[] args) {
|
|
||||||
* //setup Bytes and byte[]s to write from and read to
|
|
||||||
* Bytes b = Bytes.elasticByteBuffer();
|
|
||||||
* byte[] toWriteFrom = HELLO_WORLD.getBytes(ISO_8859);
|
|
||||||
* byte[] toReadTo = new byte[HELLO_WORLD.length()];
|
|
||||||
*
|
|
||||||
* doWrite(b, toWriteFrom);
|
|
||||||
* doRead(b, toReadTo);
|
|
||||||
*
|
|
||||||
* //check result
|
|
||||||
* final StringBuilder sb = new StringBuilder();
|
|
||||||
* for (int i = 0; i < HELLO_WORLD.length(); i++) {
|
|
||||||
* sb.append((char) toReadTo[i]);
|
|
||||||
* }
|
|
||||||
* assert sb.toString().equals(HELLO_WORLD): "Failed - strings not equal!";
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doWrite(Bytes b, byte[] toWrite) {
|
|
||||||
* //no garbage when writing to Bytes from byte[]
|
|
||||||
* b.clear();
|
|
||||||
* b.write(toWrite);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* private static void doRead(Bytes b, byte[] toReadTo) {
|
|
||||||
* //no garbage when reading from Bytes into byte[]
|
|
||||||
* b.read( toReadTo, 0, HELLO_WORLD.length());
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param byteArray to wrap
|
|
||||||
* @return the Bytes ready for writing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<byte[]> wrapForWrite( byte[] byteArray) {
|
|
||||||
BytesStore bs = BytesStore.wrap(byteArray);
|
|
||||||
try {
|
|
||||||
return bs.bytesForWrite();
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert text to bytes using ISO-8859-1 encoding and return a Bytes ready for reading.
|
|
||||||
* <p>
|
|
||||||
* Note: this returns a direct Bytes now
|
|
||||||
*
|
|
||||||
* @param text to convert
|
|
||||||
* @return Bytes ready for reading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<?> from( CharSequence text) {
|
|
||||||
return from(text.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
static Bytes<?> fromString(String text) {
|
|
||||||
return from(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert text to bytes using ISO-8859-1 encoding and return a Bytes ready for reading.
|
|
||||||
* <p>
|
|
||||||
* Note: this returns a direct Bytes now
|
|
||||||
*
|
|
||||||
* @param text to convert
|
|
||||||
* @return Bytes ready for reading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<?> directFrom( String text) {
|
|
||||||
NativeBytesStore from = NativeBytesStore.from(text);
|
|
||||||
try {
|
|
||||||
return from.bytesForRead();
|
|
||||||
} finally {
|
|
||||||
from.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert text to bytes using ISO-8859-1 encoding and return a Bytes ready for reading.
|
|
||||||
* <p>
|
|
||||||
* Note: this returns a heap Bytes
|
|
||||||
*
|
|
||||||
* @param text to convert
|
|
||||||
* @return Bytes ready for reading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Bytes<byte[]> from( String text) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
return wrapForRead(text.getBytes(StandardCharsets.ISO_8859_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@UsedViaReflection
|
|
||||||
static Bytes<byte[]> valueOf(String text) {
|
|
||||||
return from(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new fix sized wrapper for native (64-bit address)
|
|
||||||
* memory with the given {@code capacity}.
|
|
||||||
*
|
|
||||||
* @param capacity the non-negative capacity given in bytes
|
|
||||||
* @return a new fix sized wrapper for native (64-bit address)
|
|
||||||
* memory with the given {@code capacity}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VanillaBytes<Void> allocateDirect(long capacity) throws IllegalArgumentException {
|
|
||||||
NativeBytesStore<Void> bs = NativeBytesStore.nativeStoreWithFixedCapacity(capacity);
|
|
||||||
try {
|
|
||||||
return new VanillaBytes<>(bs);
|
|
||||||
} finally {
|
|
||||||
bs.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for native (64-bit address)
|
|
||||||
* memory with zero initial capacity which will be resized as required.
|
|
||||||
*
|
|
||||||
* @return a new elastic wrapper for native (64-bit address)
|
|
||||||
* memory with zero initial capacity which will be resized as required
|
|
||||||
*/
|
|
||||||
|
|
||||||
static NativeBytes<Void> allocateElasticDirect() {
|
|
||||||
return NativeBytes.nativeBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new elastic wrapper for native (64-bit address)
|
|
||||||
* memory with the given {@code initialCapacity} which will be resized as required.
|
|
||||||
*
|
|
||||||
* @param initialCapacity the initial non-negative capacity given in bytes
|
|
||||||
* @return a new elastic wrapper for native (64-bit address)
|
|
||||||
* memory with the given {@code initialCapacity} which will be resized as required
|
|
||||||
*/
|
|
||||||
|
|
||||||
static NativeBytes<Void> allocateElasticDirect(long initialCapacity) throws IllegalArgumentException {
|
|
||||||
return NativeBytes.nativeBytes(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static OnHeapBytes allocateElasticOnHeap() {
|
|
||||||
return allocateElasticOnHeap(32);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static OnHeapBytes allocateElasticOnHeap(int initialCapacity) {
|
|
||||||
HeapBytesStore<byte[]> wrap = HeapBytesStore.wrap(new byte[initialCapacity]);
|
|
||||||
try {
|
|
||||||
return new OnHeapBytes(wrap, true);
|
|
||||||
} finally {
|
|
||||||
wrap.release(INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a string from the {@code position} to the {@code limit}, The buffer is not modified
|
|
||||||
* by this call
|
|
||||||
*
|
|
||||||
* @param buffer the buffer to use
|
|
||||||
* @return a string contain the text from the {@code position} to the {@code limit}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static String toString( final Bytes<?> buffer) throws BufferUnderflowException {
|
|
||||||
return toString(buffer, MAX_HEAP_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a string from the {@code position} to the {@code limit}, The buffer is not modified
|
|
||||||
* by this call
|
|
||||||
*
|
|
||||||
* @param buffer the buffer to use
|
|
||||||
* @param maxLen of the result returned
|
|
||||||
* @return a string contain the text from the {@code position} to the {@code limit}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static String toString( final Bytes<?> buffer, long maxLen) throws
|
|
||||||
BufferUnderflowException {
|
|
||||||
|
|
||||||
if (buffer.refCount() < 1)
|
|
||||||
// added because something is crashing the JVM
|
|
||||||
return "<unknown>";
|
|
||||||
|
|
||||||
ReferenceOwner toString = ReferenceOwner.temporary("toString");
|
|
||||||
buffer.reserve(toString);
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (buffer.readRemaining() == 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
final long length = Math.min(maxLen + 1, buffer.readRemaining());
|
|
||||||
|
|
||||||
final StringBuilder builder = new StringBuilder();
|
|
||||||
try {
|
|
||||||
buffer.readWithLength(length, b -> {
|
|
||||||
while (buffer.readRemaining() > 0) {
|
|
||||||
if (builder.length() >= maxLen) {
|
|
||||||
builder.append("...");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
builder.append((char) buffer.readByte());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
builder.append(' ').append(e);
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
} finally {
|
|
||||||
buffer.release(toString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The buffer is not modified by this call
|
|
||||||
*
|
|
||||||
* @param buffer the buffer to use
|
|
||||||
* @param position the position to create the string from
|
|
||||||
* @param len the number of characters to show in the string
|
|
||||||
* @return a string contain the text from offset {@code position}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static String toString( final Bytes buffer, long position, long len)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
final long pos = buffer.readPosition();
|
|
||||||
final long limit = buffer.readLimit();
|
|
||||||
buffer.readPositionRemaining(position, len);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
final StringBuilder builder = new StringBuilder();
|
|
||||||
while (buffer.readRemaining() > 0) {
|
|
||||||
builder.append((char) buffer.readByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the last comma
|
|
||||||
return builder.toString();
|
|
||||||
} finally {
|
|
||||||
buffer.readLimit(limit);
|
|
||||||
buffer.readPosition(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new fix sized wrapper for native (64-bit address)
|
|
||||||
* memory with the contents copied from the given {@code bytes} array.
|
|
||||||
* <p>
|
|
||||||
* Changes in the given {@code bytes} will not be affected by writes in
|
|
||||||
* the returned wrapper or vice versa.
|
|
||||||
*
|
|
||||||
* @param bytes array to copy
|
|
||||||
* @return a new fix sized wrapper for native (64-bit address)
|
|
||||||
* memory with the contents copied from the given {@code bytes} array
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VanillaBytes allocateDirect( byte[] bytes) throws IllegalArgumentException {
|
|
||||||
VanillaBytes<Void> result = allocateDirect(bytes.length);
|
|
||||||
try {
|
|
||||||
result.write(bytes);
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Bytes fromHexString( String s) {
|
|
||||||
return BytesInternal.fromHexString(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Code shared by String and StringBuffer to do searches. The
|
|
||||||
* source is the character array being searched, and the target
|
|
||||||
* is the string being searched for.
|
|
||||||
*
|
|
||||||
* @param source the read bytes being searched.
|
|
||||||
* @param target the read bytes being searched for.
|
|
||||||
* @param fromIndex the index to begin searching from,
|
|
||||||
* @return the index of where the text was found.
|
|
||||||
*/
|
|
||||||
static int indexOf( BytesStore source, BytesStore target, int fromIndex) {
|
|
||||||
|
|
||||||
long sourceOffset = source.readPosition();
|
|
||||||
long targetOffset = target.readPosition();
|
|
||||||
long sourceCount = source.readRemaining();
|
|
||||||
long targetCount = target.readRemaining();
|
|
||||||
|
|
||||||
if (fromIndex >= sourceCount) {
|
|
||||||
return Math.toIntExact(targetCount == 0 ? sourceCount : -1);
|
|
||||||
}
|
|
||||||
if (fromIndex < 0) {
|
|
||||||
fromIndex = 0;
|
|
||||||
}
|
|
||||||
if (targetCount == 0) {
|
|
||||||
return fromIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte firstByte = target.readByte(targetOffset);
|
|
||||||
long max = sourceOffset + (sourceCount - targetCount);
|
|
||||||
|
|
||||||
for (long i = sourceOffset + fromIndex; i <= max; i++) {
|
|
||||||
/* Look for first character. */
|
|
||||||
if (source.readByte(i) != firstByte) {
|
|
||||||
while (++i <= max && source.readByte(i) != firstByte) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Found first character, now look at the rest of v2 */
|
|
||||||
if (i <= max) {
|
|
||||||
long j = i + 1;
|
|
||||||
long end = j + targetCount - 1;
|
|
||||||
for (long k = targetOffset + 1; j < end && source.readByte(j) == target.readByte(k); j++, k++) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j == end) {
|
|
||||||
/* Found whole string. */
|
|
||||||
return Math.toIntExact(i - sourceOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a Bytes which is optionally unchecked. This allows bounds checks to be turned off.
|
|
||||||
* Note: this means that the result is no longer elastic, even if <code>this</code> is elastic.
|
|
||||||
*
|
|
||||||
* @param unchecked if true, minimal bounds checks will be performed.
|
|
||||||
* @return Bytes without bounds checking.
|
|
||||||
* @throws IllegalStateException if the underlying BytesStore has been released
|
|
||||||
*/
|
|
||||||
|
|
||||||
default Bytes<Underlying> unchecked(boolean unchecked) throws IllegalStateException {
|
|
||||||
if (unchecked) {
|
|
||||||
if (isElastic())
|
|
||||||
BytesUtil.WarnUncheckedElasticBytes.warn();
|
|
||||||
Bytes<Underlying> underlyingBytes = start() == 0 && bytesStore().isDirectMemory() ?
|
|
||||||
new UncheckedNativeBytes<>(this) :
|
|
||||||
new UncheckedBytes<>(this);
|
|
||||||
release(INIT);
|
|
||||||
return underlyingBytes;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean unchecked() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc <P>
|
|
||||||
* If this Bytes {@link #isElastic()} the {@link #safeLimit()} can be
|
|
||||||
* lower than the point it can safely write.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default long safeLimit() {
|
|
||||||
return bytesStore().safeLimit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isClear() {
|
|
||||||
return start() == readPosition() && writeLimit() == capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc <P>
|
|
||||||
* If this Bytes {@link #isElastic()} the {@link #realCapacity()} can be
|
|
||||||
* lower than the virtual {@link #capacity()}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default long realCapacity() {
|
|
||||||
return BytesStore.super.realCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a copy of this Bytes from position() to limit().
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
BytesStore<Bytes<Underlying>, Underlying> copy();
|
|
||||||
|
|
||||||
|
|
||||||
default String toHexString() {
|
|
||||||
return toHexString(1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* display the hex data of {@link Bytes} from the position() to the limit()
|
|
||||||
*
|
|
||||||
* @param maxLength limit the number of bytes to be dumped.
|
|
||||||
* @return hex representation of the buffer, from example [0D ,OA, FF]
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String toHexString(long maxLength) {
|
|
||||||
return toHexString(readPosition(), maxLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* display the hex data of {@link Bytes} from the position() to the limit()
|
|
||||||
*
|
|
||||||
* @param maxLength limit the number of bytes to be dumped.
|
|
||||||
* @return hex representation of the buffer, from example [0D ,OA, FF]
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String toHexString(long offset, long maxLength) {
|
|
||||||
// if (Jvm.isDebug() && Jvm.stackTraceEndsWith("Bytes", 3))
|
|
||||||
// return "Not Available";
|
|
||||||
|
|
||||||
long maxLength2 = Math.min(maxLength, readLimit() - offset);
|
|
||||||
String ret = BytesInternal.toHexString(this, offset, maxLength2);
|
|
||||||
return maxLength2 < readLimit() - offset ? ret + "... truncated" : ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if this Bytes is elastic. I.e. it can resize when more data is written
|
|
||||||
* than it's {@link #realCapacity()}.
|
|
||||||
*
|
|
||||||
* @return if this Bytes is elastic
|
|
||||||
*/
|
|
||||||
boolean isElastic();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* grow the buffer if the buffer is elastic, if the buffer is not elastic and there is not
|
|
||||||
* enough capacity then this method will throws {@link java.nio.BufferOverflowException}
|
|
||||||
*
|
|
||||||
* @param size the capacity that you required
|
|
||||||
* @throws IllegalArgumentException if the buffer is not elastic and there is not enough space
|
|
||||||
*/
|
|
||||||
default void ensureCapacity(long size) throws IllegalArgumentException {
|
|
||||||
if (size > capacity())
|
|
||||||
throw new IllegalArgumentException(isElastic() ? "todo" : "not elastic");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a slice of the current Bytes based on its position() and limit(). As a sub-section
|
|
||||||
* of a Bytes it cannot be elastic.
|
|
||||||
*
|
|
||||||
* @return a slice of the existing Bytes where the start is moved to the position and the
|
|
||||||
* current limit determines the capacity.
|
|
||||||
* @throws IllegalStateException if the underlying BytesStore has been released
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default Bytes<Underlying> bytesForRead() throws IllegalStateException {
|
|
||||||
return isClear() ? BytesStore.super.bytesForRead() : new SubBytes<>(this, readPosition(), readLimit() + start());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ByteStore this Bytes wraps.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
BytesStore bytesStore();
|
|
||||||
|
|
||||||
default boolean isEqual(String s) {
|
|
||||||
return StringUtils.isEqual(this, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compact these Bytes by moving the readPosition to the start.
|
|
||||||
*
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bytes<Underlying> compact();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* copy bytes from one ByteStore to another
|
|
||||||
*
|
|
||||||
* @param store to copy to
|
|
||||||
* @return the number of bytes copied.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default long copyTo( BytesStore store) {
|
|
||||||
return BytesStore.super.copyTo(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default void copyTo( OutputStream out) throws IOException {
|
|
||||||
BytesStore.super.copyTo(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean sharedMemory() {
|
|
||||||
return bytesStore().sharedMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* will unwrite from the offset upto the current write position of the destination bytes
|
|
||||||
*
|
|
||||||
* @param fromOffset the offset from the target byytes
|
|
||||||
* @param count the number of bytes to un-write
|
|
||||||
*/
|
|
||||||
default void unwrite(long fromOffset, int count) {
|
|
||||||
long wp = writePosition();
|
|
||||||
|
|
||||||
if (wp < fromOffset)
|
|
||||||
return;
|
|
||||||
|
|
||||||
write(fromOffset, this, fromOffset + count, wp - fromOffset - count);
|
|
||||||
writeSkip(-count);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default BigDecimal readBigDecimal() {
|
|
||||||
return new BigDecimal(readBigInteger(), Maths.toUInt31(readStopBit()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default BigInteger readBigInteger() {
|
|
||||||
int length = Maths.toUInt31(readStopBit());
|
|
||||||
if (length == 0)
|
|
||||||
if (lenient())
|
|
||||||
return BigInteger.ZERO;
|
|
||||||
else
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
byte[] bytes = new byte[length];
|
|
||||||
read(bytes);
|
|
||||||
return new BigInteger(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index within this bytes of the first occurrence of the
|
|
||||||
* specified sub-bytes.
|
|
||||||
* <p>
|
|
||||||
* <p>The returned index is the smallest value <i>k</i> for which:
|
|
||||||
* <blockquote><pre>
|
|
||||||
* this.startsWith(bytes, <i>k</i>)
|
|
||||||
* </pre></blockquote>
|
|
||||||
* If no such value of <i>k</i> exists, then {@code -1} is returned.
|
|
||||||
*
|
|
||||||
* @param source the sub-bytes to search for.
|
|
||||||
* @return the index of the first occurrence of the specified sub-bytes,
|
|
||||||
* or {@code -1} if there is no such occurrence.
|
|
||||||
*/
|
|
||||||
default long indexOf( Bytes source) {
|
|
||||||
return indexOf(source, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index within this bytes of the first occurrence of the
|
|
||||||
* specified subbytes.
|
|
||||||
* <p>
|
|
||||||
* <p>The returned index is the smallest value <i>k</i> for which:
|
|
||||||
* <blockquote><pre>
|
|
||||||
* this.startsWith(bytes, <i>k</i>)
|
|
||||||
* </pre></blockquote>
|
|
||||||
* If no such value of <i>k</i> exists, then {@code -1} is returned.
|
|
||||||
*
|
|
||||||
* @param source the sub-bytes to search for.
|
|
||||||
* @param fromIndex start the seach from this offset
|
|
||||||
* @return the index of the first occurrence of the specified sub-bytes,
|
|
||||||
* or {@code -1} if there is no such occurrence.
|
|
||||||
*/
|
|
||||||
default int indexOf( BytesStore source, int fromIndex) {
|
|
||||||
return indexOf(this, source, fromIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default long indexOf( Bytes source, int fromIndex) {
|
|
||||||
return indexOf(this, source, fromIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
Bytes<Underlying> clear();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean readWrite() {
|
|
||||||
return bytesStore().readWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
default void readWithLength(long length, BytesOut<Underlying> bytesOut)
|
|
||||||
throws BufferUnderflowException, IORuntimeException {
|
|
||||||
if (length > readRemaining())
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
long limit0 = readLimit();
|
|
||||||
long limit = readPosition() + length;
|
|
||||||
boolean lenient = lenient();
|
|
||||||
try {
|
|
||||||
lenient(true);
|
|
||||||
readLimit(limit);
|
|
||||||
bytesOut.write(this);
|
|
||||||
} finally {
|
|
||||||
readLimit(limit0);
|
|
||||||
readPosition(limit);
|
|
||||||
lenient(lenient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T extends ReadBytesMarshallable> T readMarshallableLength16(Class<T> tClass, T object) {
|
|
||||||
if (object == null) object = ObjectUtils.newInstance(tClass);
|
|
||||||
int length = readUnsignedShort();
|
|
||||||
long limit = readLimit();
|
|
||||||
long end = readPosition() + length;
|
|
||||||
boolean lenient = lenient();
|
|
||||||
try {
|
|
||||||
lenient(true);
|
|
||||||
readLimit(end);
|
|
||||||
object.readMarshallable(this);
|
|
||||||
} finally {
|
|
||||||
readPosition(end);
|
|
||||||
readLimit(limit);
|
|
||||||
lenient(lenient);
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeMarshallableLength16(WriteBytesMarshallable marshallable) {
|
|
||||||
long position = writePosition();
|
|
||||||
writeUnsignedShort(0);
|
|
||||||
marshallable.writeMarshallable(this);
|
|
||||||
long length = writePosition() - position - 2;
|
|
||||||
if (length >= 1 << 16)
|
|
||||||
throw new IllegalStateException("Marshallable " + marshallable.getClass() + " too long was " + length);
|
|
||||||
writeUnsignedShort(position, (int) length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default Bytes write(final InputStream inputStream) throws IOException {
|
|
||||||
for (; ; ) {
|
|
||||||
int read;
|
|
||||||
read = inputStream.read();
|
|
||||||
if (read == -1)
|
|
||||||
break;
|
|
||||||
writeByte((byte) read);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
public interface BytesComment<B extends BytesComment<B>> {
|
|
||||||
/**
|
|
||||||
* Do these Bytes support saving comments
|
|
||||||
*
|
|
||||||
* @return true if comments are kept
|
|
||||||
*/
|
|
||||||
default boolean retainsComments() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add comment as approriate for the toHexString format
|
|
||||||
*
|
|
||||||
* @param comment to add (or ignore)
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default B comment(CharSequence comment) {
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjust the indent for nested data
|
|
||||||
*
|
|
||||||
* @param n +1 indent in, -1 reduce indenting
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default B indent(int n) {
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface BytesConsumer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves and removes the head of this queue, or returns {@code true} if this queue is
|
|
||||||
* empty.
|
|
||||||
*
|
|
||||||
* @param bytes to read into
|
|
||||||
* @return false if this queue is empty
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
boolean read(BytesOut bytes) throws BufferOverflowException;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
|
|
||||||
public interface BytesContext extends Closeable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a bytes to write to
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
Bytes bytes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the key to be written to
|
|
||||||
*/
|
|
||||||
int key();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean isClosed() {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
default void rollbackOnClose() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.util.ObjectUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface BytesIn<Underlying> extends
|
|
||||||
RandomDataInput,
|
|
||||||
ByteStringParser<Bytes<Underlying>> {
|
|
||||||
/**
|
|
||||||
* Reads messages from this tails as methods. It returns a BooleanSupplier which returns
|
|
||||||
*
|
|
||||||
* @param objects which implement the methods serialized to the file.
|
|
||||||
* @return a reader which will read one Excerpt at a time
|
|
||||||
*/
|
|
||||||
|
|
||||||
default MethodReader bytesMethodReader(Object... objects) {
|
|
||||||
return new BytesMethodReaderBuilder(this).build(objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default BytesMethodReaderBuilder bytesMethodReaderBuilder() {
|
|
||||||
return new BytesMethodReaderBuilder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
<T extends ReadBytesMarshallable> T readMarshallableLength16(Class<T> tClass, T object);
|
|
||||||
|
|
||||||
default <T> T readObject(Class<T> componentType0) {
|
|
||||||
Class<T> componentType = ObjectUtils.implementationToUse(componentType0);
|
|
||||||
if (BytesMarshallable.class.isAssignableFrom(componentType)) {
|
|
||||||
BytesMarshallable bm = (BytesMarshallable) ObjectUtils.newInstance(componentType);
|
|
||||||
bm.readMarshallable(this);
|
|
||||||
return (T) bm;
|
|
||||||
}
|
|
||||||
if (Enum.class.isAssignableFrom(componentType)) {
|
|
||||||
return (T) readEnum((Class) componentType);
|
|
||||||
}
|
|
||||||
switch (componentType.getName()) {
|
|
||||||
case "java.lang.String":
|
|
||||||
return (T) readUtf8();
|
|
||||||
case "java.lang.Double":
|
|
||||||
return (T) (Double) readDouble();
|
|
||||||
case "java.lang.Long":
|
|
||||||
return (T) (Long) readLong();
|
|
||||||
case "java.lang.Integer":
|
|
||||||
return (T) (Integer) readInt();
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (BytesMarshallable.class.isAssignableFrom(componentType)) {
|
|
||||||
BytesMarshallable bm = (BytesMarshallable) ObjectUtils.newInstance(componentType);
|
|
||||||
bm.readMarshallable(this);
|
|
||||||
return (T) bm;
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException("Unsupported " + componentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.annotation.DontChain;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object which can be read or written directly to Bytes in a streaming manner.
|
|
||||||
*/
|
|
||||||
@DontChain
|
|
||||||
public interface BytesMarshallable extends ReadBytesMarshallable, WriteBytesMarshallable {
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
default void readMarshallable(BytesIn bytes) throws IORuntimeException {
|
|
||||||
BytesUtil.readMarshallable(this, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
default void writeMarshallable(BytesOut bytes) {
|
|
||||||
BytesUtil.writeMarshallable(this, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
default String $toString() {
|
|
||||||
HexDumpBytes bytes = new HexDumpBytes();
|
|
||||||
writeMarshallable(bytes);
|
|
||||||
String s = "# " + getClass().getName() + "\n" + bytes.toHexString();
|
|
||||||
bytes.releaseLast();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,759 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.ClassLocal;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.util.ObjectUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class BytesMarshaller<T> {
|
|
||||||
public static final ClassLocal<BytesMarshaller> BYTES_MARSHALLER_CL
|
|
||||||
= ClassLocal.withInitial(BytesMarshaller::new);
|
|
||||||
private final FieldAccess[] fields;
|
|
||||||
|
|
||||||
public BytesMarshaller( Class<T> tClass) {
|
|
||||||
Map<String, Field> map = new LinkedHashMap<>();
|
|
||||||
getAllField(tClass, map);
|
|
||||||
fields = map.values().stream()
|
|
||||||
.map(FieldAccess::create).toArray(FieldAccess[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getAllField( Class clazz, Map<String, Field> map) {
|
|
||||||
if (clazz != Object.class)
|
|
||||||
getAllField(clazz.getSuperclass(), map);
|
|
||||||
for ( Field field : clazz.getDeclaredFields()) {
|
|
||||||
if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0)
|
|
||||||
continue;
|
|
||||||
Jvm.setAccessible(field);
|
|
||||||
map.put(field.getName(), field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void readMarshallable(ReadBytesMarshallable t, BytesIn in) {
|
|
||||||
for ( FieldAccess field : fields) {
|
|
||||||
field.read(t, in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeMarshallable(WriteBytesMarshallable t, BytesOut out) {
|
|
||||||
out.indent(+1);
|
|
||||||
for ( FieldAccess field : fields) {
|
|
||||||
field.write(t, out);
|
|
||||||
}
|
|
||||||
out.indent(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static abstract class FieldAccess<T> {
|
|
||||||
final Field field;
|
|
||||||
|
|
||||||
FieldAccess(Field field) {
|
|
||||||
this.field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static Object create( Field field) {
|
|
||||||
Class<?> type = field.getType();
|
|
||||||
switch (type.getName()) {
|
|
||||||
case "boolean":
|
|
||||||
return new BooleanFieldAccess(field);
|
|
||||||
case "byte":
|
|
||||||
return new ByteFieldAccess(field);
|
|
||||||
case "char":
|
|
||||||
return new CharFieldAccess(field);
|
|
||||||
case "short":
|
|
||||||
return new ShortFieldAccess(field);
|
|
||||||
case "int":
|
|
||||||
return new IntegerFieldAccess(field);
|
|
||||||
case "float":
|
|
||||||
return new FloatFieldAccess(field);
|
|
||||||
case "long":
|
|
||||||
return new LongFieldAccess(field);
|
|
||||||
case "double":
|
|
||||||
return new DoubleFieldAccess(field);
|
|
||||||
default:
|
|
||||||
if (type.isArray()) {
|
|
||||||
if (type.getComponentType().isPrimitive()) {
|
|
||||||
if (type == byte[].class)
|
|
||||||
return new ByteArrayFieldAccess(field);
|
|
||||||
if (type == int[].class)
|
|
||||||
return new IntArrayFieldAccess(field);
|
|
||||||
if (type == float[].class)
|
|
||||||
return new FloatArrayFieldAccess(field);
|
|
||||||
if (type == long[].class)
|
|
||||||
return new LongArrayFieldAccess(field);
|
|
||||||
if (type == double[].class)
|
|
||||||
return new DoubleArrayFieldAccess(field);
|
|
||||||
throw new UnsupportedOperationException("TODO " + field.getType());
|
|
||||||
}
|
|
||||||
return new ObjectArrayFieldAccess(field);
|
|
||||||
}
|
|
||||||
if (Collection.class.isAssignableFrom(type))
|
|
||||||
return new CollectionFieldAccess(field);
|
|
||||||
if (Map.class.isAssignableFrom(type))
|
|
||||||
return new MapFieldAccess(field);
|
|
||||||
if (BytesStore.class.isAssignableFrom(type))
|
|
||||||
return new BytesFieldAccess(field);
|
|
||||||
if (BytesMarshallable.class.isAssignableFrom(type))
|
|
||||||
return new BytesMarshallableFieldAccess(field);
|
|
||||||
return new ScalarFieldAccess(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Class extractClass(Type type0) {
|
|
||||||
if (type0 instanceof Class)
|
|
||||||
return (Class) type0;
|
|
||||||
else if (type0 instanceof ParameterizedType)
|
|
||||||
return (Class) ((ParameterizedType) type0).getRawType();
|
|
||||||
else
|
|
||||||
return Object.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getSimpleName() + "{" +
|
|
||||||
"field=" + field +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(Object o, BytesOut write) {
|
|
||||||
try {
|
|
||||||
write.comment(field.getName());
|
|
||||||
getValue(o, write);
|
|
||||||
} catch (IllegalAccessException iae) {
|
|
||||||
throw new AssertionError(iae);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void getValue(Object o, BytesOut write) throws IllegalAccessException;
|
|
||||||
|
|
||||||
void read(Object o, BytesIn read) {
|
|
||||||
try {
|
|
||||||
setValue(o, read);
|
|
||||||
} catch (IllegalAccessException iae) {
|
|
||||||
throw new AssertionError(iae);
|
|
||||||
} catch (IORuntimeException e) {
|
|
||||||
throw Jvm.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void setValue(Object o, BytesIn read) throws IllegalAccessException, IORuntimeException;
|
|
||||||
|
|
||||||
|
|
||||||
protected Supplier<Map> newInstance( Class type) {
|
|
||||||
try {
|
|
||||||
return (Supplier<Map>) type.newInstance();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
throw Jvm.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ScalarFieldAccess extends FieldAccess<Object> {
|
|
||||||
public ScalarFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
Object o2 = field.get(o);
|
|
||||||
String s = o2 == null ? null : o2.toString();
|
|
||||||
write.writeUtf8(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException, IORuntimeException {
|
|
||||||
String s = read.readUtf8();
|
|
||||||
field.set(o, ObjectUtils.convertTo(field.getType(), s));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BytesMarshallableFieldAccess extends FieldAccess<Object> {
|
|
||||||
public BytesMarshallableFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
BytesMarshallable o2 = (BytesMarshallable) field.get(o);
|
|
||||||
assert o2 != null;
|
|
||||||
o2.writeMarshallable(write);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException, IORuntimeException {
|
|
||||||
BytesMarshallable o2 = (BytesMarshallable) field.get(o);
|
|
||||||
if (!field.getType().isInstance(o2))
|
|
||||||
field.set(o, o2 = (BytesMarshallable) ObjectUtils.newInstance((Class) field.getType()));
|
|
||||||
|
|
||||||
o2.readMarshallable(read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BytesFieldAccess extends FieldAccess<Bytes> {
|
|
||||||
public BytesFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
BytesStore bytes = (BytesStore) field.get(o);
|
|
||||||
if (bytes == null) {
|
|
||||||
write.writeStopBit(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long offset = bytes.readPosition();
|
|
||||||
long length = bytes.readRemaining();
|
|
||||||
write.writeStopBit(length);
|
|
||||||
write.write(bytes, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException, IORuntimeException {
|
|
||||||
Bytes bytes = (Bytes) field.get(o);
|
|
||||||
long stopBit = read.readStopBit();
|
|
||||||
if (stopBit == -1) {
|
|
||||||
if (bytes != null)
|
|
||||||
bytes.releaseLast();
|
|
||||||
field.set(o, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int length = Maths.toUInt31(stopBit);
|
|
||||||
Bytes bs;
|
|
||||||
if (bytes == null) {
|
|
||||||
bs = Bytes.allocateElasticOnHeap(length);
|
|
||||||
field.set(o, bs);
|
|
||||||
} else {
|
|
||||||
bs = bytes;
|
|
||||||
}
|
|
||||||
bs.clear();
|
|
||||||
read.read(bs, length);
|
|
||||||
bs.readLimit(length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static class ArrayFieldAccess extends FieldAccess {
|
|
||||||
private final Class componentType;
|
|
||||||
|
|
||||||
public ArrayFieldAccess( Field field) {
|
|
||||||
super(field);
|
|
||||||
componentType = field.getType().getComponentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
throw new UnsupportedOperationException("TODO");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
throw new UnsupportedOperationException("TODO");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static class ObjectArrayFieldAccess extends FieldAccess {
|
|
||||||
Class componentType;
|
|
||||||
|
|
||||||
public ObjectArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
componentType = field.getType().getComponentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
Object[] c = (Object[]) field.get(o);
|
|
||||||
if (c == null) {
|
|
||||||
write.writeStopBit(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int size = c.length;
|
|
||||||
write.writeStopBit(size);
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
write.writeObject(componentType, c[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
Object[] c = (Object[]) field.get(o);
|
|
||||||
int length = Maths.toInt32(read.readStopBit());
|
|
||||||
if (length < 0) {
|
|
||||||
if (c != null)
|
|
||||||
field.set(o, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c == null)
|
|
||||||
field.set(o, c = (Object[]) Array.newInstance(field.getType().getComponentType(), length));
|
|
||||||
else if (c.length != length)
|
|
||||||
field.set(o, c = Arrays.copyOf(c, length));
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
Object o2 = c[i];
|
|
||||||
if (o2 instanceof BytesMarshallable)
|
|
||||||
((BytesMarshallable) o2).readMarshallable(read);
|
|
||||||
else
|
|
||||||
c[i] = read.readObject(componentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CollectionFieldAccess extends FieldAccess {
|
|
||||||
final Supplier<Collection> collectionSupplier;
|
|
||||||
|
|
||||||
private final Class componentType;
|
|
||||||
private final Class<?> type;
|
|
||||||
|
|
||||||
public CollectionFieldAccess( Field field) {
|
|
||||||
super(field);
|
|
||||||
type = field.getType();
|
|
||||||
if (type == List.class || type == Collection.class)
|
|
||||||
collectionSupplier = ArrayList::new;
|
|
||||||
else if (type == SortedSet.class || type == NavigableSet.class)
|
|
||||||
collectionSupplier = TreeSet::new;
|
|
||||||
else if (type == Set.class)
|
|
||||||
collectionSupplier = LinkedHashSet::new;
|
|
||||||
else
|
|
||||||
collectionSupplier = newInstance(type);
|
|
||||||
Type genericType = field.getGenericType();
|
|
||||||
if (genericType instanceof ParameterizedType) {
|
|
||||||
ParameterizedType pType = (ParameterizedType) genericType;
|
|
||||||
Type type0 = pType.getActualTypeArguments()[0];
|
|
||||||
componentType = extractClass(type0);
|
|
||||||
} else {
|
|
||||||
componentType = Object.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
Collection c = (Collection) field.get(o);
|
|
||||||
if (c == null) {
|
|
||||||
write.writeStopBit(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
write.writeStopBit(c.size());
|
|
||||||
if (c.isEmpty())
|
|
||||||
return;
|
|
||||||
if (c instanceof RandomAccess && c instanceof List) {
|
|
||||||
List l = (List) c;
|
|
||||||
for (int i = 0, size = l.size(); i < size; i++)
|
|
||||||
write.writeObject(componentType, l.get(i));
|
|
||||||
} else {
|
|
||||||
for (Object o2 : c) {
|
|
||||||
write.writeObject(componentType, o2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
Collection c = (Collection) field.get(o);
|
|
||||||
int length = Maths.toInt32(read.readStopBit());
|
|
||||||
if (length < 0) {
|
|
||||||
if (c != null)
|
|
||||||
field.set(o, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c.clear();
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
c.add(read.readObject(componentType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class MapFieldAccess extends FieldAccess {
|
|
||||||
final Supplier<Map> collectionSupplier;
|
|
||||||
private final Class<?> type;
|
|
||||||
|
|
||||||
private final Class keyType;
|
|
||||||
|
|
||||||
private final Class valueType;
|
|
||||||
|
|
||||||
public MapFieldAccess( Field field) {
|
|
||||||
super(field);
|
|
||||||
type = field.getType();
|
|
||||||
if (type == Map.class)
|
|
||||||
collectionSupplier = LinkedHashMap::new;
|
|
||||||
else if (type == SortedMap.class || type == NavigableMap.class)
|
|
||||||
collectionSupplier = TreeMap::new;
|
|
||||||
else
|
|
||||||
collectionSupplier = newInstance(type);
|
|
||||||
Type genericType = field.getGenericType();
|
|
||||||
if (genericType instanceof ParameterizedType) {
|
|
||||||
ParameterizedType pType = (ParameterizedType) genericType;
|
|
||||||
Type[] actualTypeArguments = pType.getActualTypeArguments();
|
|
||||||
keyType = extractClass(actualTypeArguments[0]);
|
|
||||||
valueType = extractClass(actualTypeArguments[1]);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
keyType = Object.class;
|
|
||||||
valueType = Object.class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
Map<?, ?> m = (Map) field.get(o);
|
|
||||||
if (m == null) {
|
|
||||||
write.writeStopBit(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
write.writeStopBit(m.size());
|
|
||||||
for (Map.Entry<?, ?> entry : m.entrySet()) {
|
|
||||||
write.writeObject(keyType, entry.getKey());
|
|
||||||
write.writeObject(valueType, entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
Map m = (Map) field.get(o);
|
|
||||||
long length = read.readStopBit();
|
|
||||||
if (length < 0) {
|
|
||||||
if (m != null)
|
|
||||||
field.set(o, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m == null) {
|
|
||||||
field.set(o, m = new LinkedHashMap<>());
|
|
||||||
} else {
|
|
||||||
m.clear();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
m.put(read.readObject(keyType), read.readObject(valueType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class BooleanFieldAccess extends FieldAccess {
|
|
||||||
public BooleanFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeBoolean(field.getBoolean(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setBoolean(o, read.readBoolean());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ByteFieldAccess extends FieldAccess {
|
|
||||||
public ByteFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeByte(field.getByte(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setByte(o, read.readByte());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ByteArrayFieldAccess extends FieldAccess {
|
|
||||||
public ByteArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
byte[] array = (byte[]) field.get(o);
|
|
||||||
if (array == null) {
|
|
||||||
write.writeInt(~0);
|
|
||||||
} else {
|
|
||||||
write.writeInt(array.length);
|
|
||||||
for (int i = 0; i < array.length; i++)
|
|
||||||
write.writeByte(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
int len = read.readInt();
|
|
||||||
if (len == ~0) {
|
|
||||||
field.set(o, null);
|
|
||||||
} else if (len >= 0) {
|
|
||||||
byte[] array = (byte[]) field.get(o);
|
|
||||||
if (array == null || array.length != len) {
|
|
||||||
array = new byte[len];
|
|
||||||
field.set(o, array);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
array[i] = read.readByte();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CharFieldAccess extends FieldAccess {
|
|
||||||
public CharFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
char aChar = field.getChar(o);
|
|
||||||
if (aChar >= 65536 - 127)
|
|
||||||
write.writeStopBit(aChar - 65536);
|
|
||||||
else
|
|
||||||
write.writeStopBit(aChar);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setChar(o, read.readStopBitChar());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ShortFieldAccess extends FieldAccess {
|
|
||||||
public ShortFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeShort(field.getShort(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setShort(o, read.readShort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class IntegerFieldAccess extends FieldAccess {
|
|
||||||
public IntegerFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeInt(field.getInt(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setInt(o, read.readInt());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class IntArrayFieldAccess extends FieldAccess {
|
|
||||||
public IntArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
int[] array = (int[]) field.get(o);
|
|
||||||
if (array == null) {
|
|
||||||
write.writeInt(~0);
|
|
||||||
} else {
|
|
||||||
write.writeInt(array.length);
|
|
||||||
for (int i = 0; i < array.length; i++)
|
|
||||||
write.writeInt(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
int len = read.readInt();
|
|
||||||
if (len == ~0) {
|
|
||||||
field.set(o, null);
|
|
||||||
} else if (len >= 0) {
|
|
||||||
int[] array = (int[]) field.get(o);
|
|
||||||
if (array == null || array.length != len) {
|
|
||||||
array = new int[len];
|
|
||||||
field.set(o, array);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
array[i] = read.readInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class FloatFieldAccess extends FieldAccess {
|
|
||||||
public FloatFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeFloat(field.getFloat(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setFloat(o, read.readFloat());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class FloatArrayFieldAccess extends FieldAccess {
|
|
||||||
public FloatArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
float[] array = (float[]) field.get(o);
|
|
||||||
if (array == null) {
|
|
||||||
write.writeInt(~0);
|
|
||||||
} else {
|
|
||||||
write.writeInt(array.length);
|
|
||||||
for (int i = 0; i < array.length; i++)
|
|
||||||
write.writeFloat(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
int len = read.readInt();
|
|
||||||
if (len == ~0) {
|
|
||||||
field.set(o, null);
|
|
||||||
} else if (len >= 0) {
|
|
||||||
float[] array = (float[]) field.get(o);
|
|
||||||
if (array == null || array.length != len) {
|
|
||||||
array = new float[len];
|
|
||||||
field.set(o, array);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
array[i] = read.readFloat();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LongFieldAccess extends FieldAccess {
|
|
||||||
public LongFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeLong(field.getLong(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setLong(o, read.readLong());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LongArrayFieldAccess extends FieldAccess {
|
|
||||||
public LongArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
long[] array = (long[]) field.get(o);
|
|
||||||
if (array == null) {
|
|
||||||
write.writeInt(~0);
|
|
||||||
} else {
|
|
||||||
write.writeInt(array.length);
|
|
||||||
for (int i = 0; i < array.length; i++)
|
|
||||||
write.writeLong(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
int len = read.readInt();
|
|
||||||
if (len == ~0) {
|
|
||||||
field.set(o, null);
|
|
||||||
} else if (len >= 0) {
|
|
||||||
long[] array = (long[]) field.get(o);
|
|
||||||
if (array == null || array.length != len) {
|
|
||||||
array = new long[len];
|
|
||||||
field.set(o, array);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
array[i] = read.readLong();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DoubleFieldAccess extends FieldAccess {
|
|
||||||
public DoubleFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
write.writeDouble(field.getDouble(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
field.setDouble(o, read.readDouble());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DoubleArrayFieldAccess extends FieldAccess {
|
|
||||||
public DoubleArrayFieldAccess(Field field) {
|
|
||||||
super(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void getValue(Object o, BytesOut write) throws IllegalAccessException {
|
|
||||||
double[] array = (double[]) field.get(o);
|
|
||||||
if (array == null) {
|
|
||||||
write.writeInt(~0);
|
|
||||||
} else {
|
|
||||||
write.writeInt(array.length);
|
|
||||||
for (int i = 0; i < array.length; i++)
|
|
||||||
write.writeDouble(array[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setValue(Object o, BytesIn read) throws IllegalAccessException {
|
|
||||||
int len = read.readInt();
|
|
||||||
if (len == ~0) {
|
|
||||||
field.set(o, null);
|
|
||||||
} else if (len >= 0) {
|
|
||||||
double[] array = (double[]) field.get(o);
|
|
||||||
if (array == null || array.length != len) {
|
|
||||||
array = new double[len];
|
|
||||||
field.set(o, array);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
array[i] = read.readDouble();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.io.SimpleCloseable;
|
|
||||||
import net.openhft.chronicle.core.util.InvocationTargetRuntimeException;
|
|
||||||
import net.openhft.chronicle.core.util.ObjectUtils;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BytesMethodReader extends SimpleCloseable implements MethodReader {
|
|
||||||
private final BytesIn in;
|
|
||||||
private final BytesParselet defaultParselet;
|
|
||||||
private final List<Consumer<BytesIn>> methodEncoders = new ArrayList<>();
|
|
||||||
private final Map<Long, Consumer<BytesIn>> methodEncoderMap = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
public BytesMethodReader(BytesIn in,
|
|
||||||
BytesParselet defaultParselet,
|
|
||||||
MethodEncoderLookup methodEncoderLookup,
|
|
||||||
Object[] objects) {
|
|
||||||
|
|
||||||
this.in = in;
|
|
||||||
this.defaultParselet = defaultParselet;
|
|
||||||
|
|
||||||
for (Object object : objects) {
|
|
||||||
for (Method method : object.getClass().getMethods()) {
|
|
||||||
MethodEncoder encoder = methodEncoderLookup.apply(method);
|
|
||||||
if (encoder != null) {
|
|
||||||
addEncoder(object, method, encoder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addEncoder(Object object, Method method, MethodEncoder encoder) {
|
|
||||||
Jvm.setAccessible(method);
|
|
||||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
|
||||||
int count = parameterTypes.length;
|
|
||||||
BytesMarshallable[][] array = new BytesMarshallable[1][count];
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
array[0][i] = (BytesMarshallable) ObjectUtils.newInstance(parameterTypes[i]);
|
|
||||||
}
|
|
||||||
Consumer<BytesIn> reader = in -> {
|
|
||||||
array[0] = (BytesMarshallable[]) encoder.decode(array[0], in);
|
|
||||||
try {
|
|
||||||
method.invoke(object, array[0]);
|
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
|
||||||
Jvm.warn().on(getClass(), "Exception calling " + method + " " + Arrays.toString(array[0]), e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
long messageId = encoder.messageId();
|
|
||||||
if (messageId >= 0 && messageId < 1000) {
|
|
||||||
while (methodEncoders.size() <= messageId)
|
|
||||||
methodEncoders.add(null);
|
|
||||||
methodEncoders.set((int) messageId, reader);
|
|
||||||
} else {
|
|
||||||
methodEncoderMap.put(messageId, reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodReaderInterceptorReturns methodReaderInterceptorReturns() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean readOne() throws InvocationTargetRuntimeException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (in.readRemaining() < 1)
|
|
||||||
return false;
|
|
||||||
long messageId = in.readStopBit();
|
|
||||||
Consumer<BytesIn> consumer;
|
|
||||||
if (messageId >= 0 && messageId < methodEncoders.size())
|
|
||||||
consumer = methodEncoders.get((int) messageId);
|
|
||||||
else
|
|
||||||
consumer = methodEncoderMap.get(messageId);
|
|
||||||
if (consumer == null) {
|
|
||||||
defaultParselet.accept(messageId, in);
|
|
||||||
} else {
|
|
||||||
consumer.accept(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodReader closeIn(boolean closeIn) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BytesMethodReaderBuilder implements MethodReaderBuilder {
|
|
||||||
private final BytesIn in;
|
|
||||||
private BytesParselet defaultParselet = createDefaultParselet();
|
|
||||||
private MethodEncoderLookup methodEncoderLookup = MethodEncoderLookup.BY_ANNOTATION;
|
|
||||||
|
|
||||||
public BytesMethodReaderBuilder(BytesIn in) {
|
|
||||||
this.in = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static BytesParselet createDefaultParselet() {
|
|
||||||
return (msg, in) -> {
|
|
||||||
Bytes bytes = (Bytes) in;
|
|
||||||
throw new IllegalArgumentException("Unknown message type " + msg + " " + bytes.toHexString());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodReaderBuilder warnMissing(boolean warnMissing) {
|
|
||||||
// always true
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodEncoderLookup methodEncoderLookup() {
|
|
||||||
return methodEncoderLookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BytesMethodReaderBuilder methodEncoderLookup(MethodEncoderLookup methodEncoderLookup) {
|
|
||||||
this.methodEncoderLookup = methodEncoderLookup;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BytesParselet defaultParselet() {
|
|
||||||
return defaultParselet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BytesMethodReaderBuilder defaultParselet(BytesParselet defaultParselet) {
|
|
||||||
this.defaultParselet = defaultParselet;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodReaderBuilder methodReaderInterceptorReturns(MethodReaderInterceptorReturns methodReaderInterceptorReturns) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BytesMethodReader build(Object... objects) {
|
|
||||||
return new BytesMethodReader(in, defaultParselet, methodEncoderLookup, objects);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
|
|
||||||
public interface BytesMethodWriterInvocationHandler extends InvocationHandler {
|
|
||||||
|
|
||||||
void onClose(Closeable closeable);
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.util.ObjectUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface BytesOut<Underlying> extends
|
|
||||||
ByteStringAppender<Bytes<Underlying>>,
|
|
||||||
BytesPrepender<Bytes<Underlying>>,
|
|
||||||
BytesComment<BytesOut<Underlying>> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy an interface so each message called is written to a file for replay.
|
|
||||||
*
|
|
||||||
* @param tClass primary interface
|
|
||||||
* @param additional any additional interfaces
|
|
||||||
* @return a proxy which implements the primary interface (additional interfaces have to be
|
|
||||||
* cast)
|
|
||||||
*/
|
|
||||||
|
|
||||||
default <T> T bytesMethodWriter( Class<T> tClass, Class... additional) {
|
|
||||||
Class[] interfaces = ObjectUtils.addAll(tClass, additional);
|
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
return (T) Proxy.newProxyInstance(tClass.getClassLoader(), interfaces,
|
|
||||||
new BinaryBytesMethodWriterInvocationHandler(MethodEncoderLookup.BY_ANNOTATION, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeMarshallableLength16(WriteBytesMarshallable marshallable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a limit set of writeObject types.
|
|
||||||
*
|
|
||||||
* @param componentType expected.
|
|
||||||
* @param obj of componentType
|
|
||||||
*/
|
|
||||||
default void writeObject(Class componentType, Object obj) {
|
|
||||||
if (!componentType.isInstance(obj))
|
|
||||||
throw new IllegalArgumentException("Cannot serialize " + obj.getClass() + " as an " + componentType);
|
|
||||||
if (obj instanceof BytesMarshallable) {
|
|
||||||
((BytesMarshallable) obj).writeMarshallable(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (obj instanceof Enum) {
|
|
||||||
writeEnum((Enum) obj);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (obj instanceof BytesStore) {
|
|
||||||
BytesStore bs = (BytesStore) obj;
|
|
||||||
writeStopBit(bs.readRemaining());
|
|
||||||
write(bs);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (componentType.getName()) {
|
|
||||||
case "java.lang.String":
|
|
||||||
writeUtf8((String) obj);
|
|
||||||
return;
|
|
||||||
case "java.lang.Double":
|
|
||||||
writeDouble((Double) obj);
|
|
||||||
return;
|
|
||||||
case "java.lang.Long":
|
|
||||||
writeLong((Long) obj);
|
|
||||||
return;
|
|
||||||
case "java.lang.Integer":
|
|
||||||
writeInt((Integer) obj);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Not supported " + componentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface BytesParselet {
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
void accept(long messageType, BytesIn in);
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
public interface BytesPrepender<B extends BytesPrepender<B>> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear a buffer, with a given padding to allow for prepending later. clearAndPad(0) is the same as clear()
|
|
||||||
*
|
|
||||||
* @param length to pad
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the length > capacity() - start()
|
|
||||||
*/
|
|
||||||
|
|
||||||
B clearAndPad(long length) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepends a long in decimal, this method moves the readPosition() backwards.
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param value to prepend as text.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the capacity of the underlying buffer was exceeded
|
|
||||||
* @throws IORuntimeException if an error occurred while attempting to resize the underlying buffer
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
|
|
||||||
default B prepend(long value) throws BufferOverflowException {
|
|
||||||
BytesInternal.prepend(this, value);
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary a byte
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param bytes to prepend to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
B prewrite(byte[] bytes) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary a byte
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param bytes to prepend to.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
|
|
||||||
B prewrite(BytesStore bytes) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary a byte
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param b byte to prepend to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
B prewriteByte(byte b) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary a 2 byte int
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param i short to prepend to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
B prewriteShort(short i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary a 4 byte int
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param i integer to prepend to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
B prewriteInt(int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write backward in binary an 8 byte long
|
|
||||||
* <p>Note: it moves the readPosition not the writePosition / readLimit</p>
|
|
||||||
*
|
|
||||||
* @param l long to prepend to.
|
|
||||||
*/
|
|
||||||
|
|
||||||
B prewriteLong(long l) throws BufferOverflowException;
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface BytesRingBuffer extends BytesRingBufferStats, BytesConsumer, Closeable {
|
|
||||||
|
|
||||||
Logger LOG = LoggerFactory.getLogger(BytesRingBuffer.class);
|
|
||||||
|
|
||||||
|
|
||||||
static BytesRingBuffer newInstance( NativeBytesStore<Void> bytesStore) {
|
|
||||||
return newInstance(bytesStore, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static MultiReaderBytesRingBuffer newInstance(
|
|
||||||
NativeBytesStore<Void> bytesStore,
|
|
||||||
int numReaders) {
|
|
||||||
try {
|
|
||||||
final Class<MultiReaderBytesRingBuffer> aClass = clazz();
|
|
||||||
final Constructor<MultiReaderBytesRingBuffer> constructor = aClass
|
|
||||||
.getDeclaredConstructor(BytesStore.class, int.class);
|
|
||||||
return constructor.newInstance(bytesStore, numReaders);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("This is a a commercial feature, please contact " +
|
|
||||||
"sales@chronicle.software to unlock this feature.");
|
|
||||||
|
|
||||||
throw Jvm.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Class<MultiReaderBytesRingBuffer> clazz() throws ClassNotFoundException {
|
|
||||||
//noinspection AccessStaticViaInstance
|
|
||||||
return (Class<MultiReaderBytesRingBuffer>) Class.forName(
|
|
||||||
"software.chronicle.enterprise.ring.EnterpriseRingBuffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
static long sizeFor(long capacity) {
|
|
||||||
return sizeFor(capacity, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long sizeFor(long capacity, int numReaders) {
|
|
||||||
try {
|
|
||||||
//noinspection AccessStaticViaInstance
|
|
||||||
final Method sizeFor = Class.forName(
|
|
||||||
"software.chronicle.enterprise.queue.ChronicleRingBuffer").getMethod("sizeFor", long.class, int.class);
|
|
||||||
return (long) sizeFor.invoke(null, capacity, numReaders);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("This is a a commercial feature, please contact " +
|
|
||||||
"sales@chronicle.software to unlock this feature.");
|
|
||||||
|
|
||||||
throw Jvm.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clears the ring buffer but moving the read position to the write position
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the specified element at the tail of this queue if it is possible to do so
|
|
||||||
* immediately without exceeding the queue's capacity,
|
|
||||||
*
|
|
||||||
* @param bytes0 the {@code bytes0} that you wish to add to the ring buffer
|
|
||||||
* @return returning {@code true} upon success and {@code false} if this queue is full.
|
|
||||||
*/
|
|
||||||
boolean offer( BytesStore bytes0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves and removes the head of this queue, or returns {@code null} if this queue is
|
|
||||||
* empty.
|
|
||||||
*
|
|
||||||
* @param using Bytes to read into.
|
|
||||||
* @return false if this queue is empty, or a populated buffer if the element was retried
|
|
||||||
* @throws BufferOverflowException is the {@code using} buffer is not large enough
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
boolean read( BytesOut using);
|
|
||||||
|
|
||||||
long readRemaining();
|
|
||||||
|
|
||||||
boolean isEmpty();
|
|
||||||
|
|
||||||
BytesStore bytesStore();
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface BytesRingBufferStats {
|
|
||||||
/**
|
|
||||||
* each time the ring is read, this logs the number of bytes in the write buffer, calling this
|
|
||||||
* method resets these statistics,
|
|
||||||
*
|
|
||||||
* @return Long.MAX_VALUE if no read calls were made since the last time this method was called.
|
|
||||||
*/
|
|
||||||
long minNumberOfWriteBytesRemaining();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the total capacity in bytes
|
|
||||||
*/
|
|
||||||
long capacity();
|
|
||||||
|
|
||||||
long getAndClearWriteCount();
|
|
||||||
|
|
||||||
long getAndClearMissedWriteCount();
|
|
||||||
|
|
||||||
long getAndClearContentionCount();
|
|
||||||
|
|
||||||
List<RingBufferReaderStats> readers();
|
|
||||||
}
|
|
|
@ -1,570 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceCounted;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import static java.lang.Math.min;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A immutable reference to some bytes with fixed extents. This can be shared safely across thread
|
|
||||||
* provided the data referenced is accessed in a thread safe manner. Only offset access within the
|
|
||||||
* capacity is possible.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface BytesStore<B extends BytesStore<B, Underlying>, Underlying>
|
|
||||||
extends RandomDataInput, RandomDataOutput<B>, ReferenceCounted, CharSequence {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method builds a BytesStore using the bytes in a CharSequence. This chars are encoded
|
|
||||||
* using ISO_8859_1
|
|
||||||
*
|
|
||||||
* @param cs to convert
|
|
||||||
* @return BytesStore
|
|
||||||
*/
|
|
||||||
static BytesStore from( CharSequence cs) {
|
|
||||||
if (cs instanceof BytesStore)
|
|
||||||
return ((BytesStore) cs).copy();
|
|
||||||
return HeapBytesStore.wrap(cs.toString().getBytes(StandardCharsets.ISO_8859_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a byte[]. This means there is one copy in memory.
|
|
||||||
*
|
|
||||||
* @param bytes to wrap
|
|
||||||
* @return BytesStore
|
|
||||||
*/
|
|
||||||
static HeapBytesStore<byte[]> wrap( byte[] bytes) {
|
|
||||||
return HeapBytesStore.wrap(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a ByteBuffer which can be either on heap or off heap.
|
|
||||||
*
|
|
||||||
* @param bb to wrap
|
|
||||||
* @return BytesStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
static BytesStore<?, ByteBuffer> wrap( ByteBuffer bb) {
|
|
||||||
return bb.isDirect()
|
|
||||||
? NativeBytesStore.wrap(bb)
|
|
||||||
: HeapBytesStore.wrap(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a PointerBytesStore which can be set to any addressForRead
|
|
||||||
*/
|
|
||||||
|
|
||||||
static PointerBytesStore nativePointer() {
|
|
||||||
return new PointerBytesStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the addressForRead and length as a BytesStore
|
|
||||||
*
|
|
||||||
* @param address for the start
|
|
||||||
* @param length of data
|
|
||||||
* @return as a BytesStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
static PointerBytesStore wrap(long address, long length) {
|
|
||||||
PointerBytesStore pbs = nativePointer();
|
|
||||||
pbs.set(address, length);
|
|
||||||
return pbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return an empty, fixed sized Bytes
|
|
||||||
*/
|
|
||||||
static BytesStore empty() {
|
|
||||||
return NoBytesStore.noBytesStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether it uses direct memory or not.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
boolean isDirectMemory();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a copy of this BytesStore.
|
|
||||||
*/
|
|
||||||
BytesStore<B, Underlying> copy();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a Bytes to wrap this ByteStore from the start() to the realCapacity().
|
|
||||||
* @throws IllegalStateException if this Bytes has been released.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default Bytes<Underlying> bytesForRead() throws IllegalStateException {
|
|
||||||
try {
|
|
||||||
Bytes<Underlying> ret = bytesForWrite();
|
|
||||||
ret.readLimit(writeLimit());
|
|
||||||
ret.writeLimit(realCapacity());
|
|
||||||
ret.readPosition(start());
|
|
||||||
return ret;
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a Bytes for writing to this BytesStore
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default Bytes<Underlying> bytesForWrite() throws IllegalStateException {
|
|
||||||
return new VanillaBytes<>(this, writePosition(), writeLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the {@code readPosition} is at the {@code start} and
|
|
||||||
* the {@code writeLimit} is at the {@code end}.
|
|
||||||
* <p>
|
|
||||||
* I.e {@code start() == readPosition() && writeLimit() == capacity()}
|
|
||||||
*
|
|
||||||
* @return if the {@code readPosition} is at the {@code start} and
|
|
||||||
* the {@code writeLimit} is at the {@code end}
|
|
||||||
*/
|
|
||||||
default boolean isClear() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the actual capacity available before resizing.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default long realCapacity() {
|
|
||||||
return capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The maximum limit you can set.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
long capacity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the underlying object being wrapped, if there is one, or null if not.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Underlying underlyingObject();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this test to determine if an offset is considered safe.
|
|
||||||
*/
|
|
||||||
default boolean inside(long offset) {
|
|
||||||
return start() <= offset && offset < safeLimit();
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean inside(long offset, long buffer) {
|
|
||||||
return start() <= offset && offset + buffer < safeLimit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return how many bytes can be safely read, i.e. what is the real capacity of the underlying data.
|
|
||||||
*/
|
|
||||||
default long safeLimit() {
|
|
||||||
return capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy the data to another BytesStore as long as there is space available in the destination store.
|
|
||||||
*
|
|
||||||
* @param store to copy to
|
|
||||||
* @return how many bytes were copied
|
|
||||||
*/
|
|
||||||
default long copyTo( BytesStore store) {
|
|
||||||
long readPos = readPosition();
|
|
||||||
long writePos = store.writePosition();
|
|
||||||
long copy = min(readRemaining(), store.capacity());
|
|
||||||
long i = 0;
|
|
||||||
try {
|
|
||||||
for (; i < copy - 7; i += 8)
|
|
||||||
store.writeLong(writePos + i, readLong(readPos + i));
|
|
||||||
for (; i < copy; i++)
|
|
||||||
store.writeByte(writePos + i, readByte(readPos + i));
|
|
||||||
} catch (BufferOverflowException | BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void copyTo( OutputStream out) throws IOException {
|
|
||||||
BytesInternal.copy(this, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill the BytesStore with zeros
|
|
||||||
*
|
|
||||||
* @param start first byte inclusive
|
|
||||||
* @param end last byte exclusive.
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
|
|
||||||
default B zeroOut(long start, long end) {
|
|
||||||
if (end <= start)
|
|
||||||
return (B) this;
|
|
||||||
if (start < start())
|
|
||||||
start = start();
|
|
||||||
if (end > capacity())
|
|
||||||
end = capacity();
|
|
||||||
long i = start;
|
|
||||||
try {
|
|
||||||
for (; i < end - 7; i += 8L)
|
|
||||||
writeLong(i, 0L);
|
|
||||||
for (; i < end; i++)
|
|
||||||
writeByte(i, 0);
|
|
||||||
} catch (BufferOverflowException | IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return (B) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is inherited from CharSequence so result should be the length of the contained
|
|
||||||
* chars sequence although it actually returns the number of underlying bytes. These 2 numbers are only the same
|
|
||||||
* if the encoding we are using is single char for single byte.
|
|
||||||
*
|
|
||||||
* @return length in bytes to read or Integer.MAX_VALUE if longer.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default int length() {
|
|
||||||
return (int) Math.min(Integer.MAX_VALUE, readRemaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assume ISO-8859-1 encoding, subclasses can override this.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
default char charAt(int index) throws IndexOutOfBoundsException {
|
|
||||||
try {
|
|
||||||
return (char) readUnsignedByte(readPosition() + index);
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new IndexOutOfBoundsException((readPosition() + index) + " >= " + readLimit());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not supported.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default CharSequence subSequence(int start, int end) {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By default the maximum length of data shown is 256 characters. Use toDebugString(long) if you want more.
|
|
||||||
*
|
|
||||||
* @return This BytesStore as a DebugString.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String toDebugString() {
|
|
||||||
return toDebugString(512);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param maxLength the maximum len of the output
|
|
||||||
* @return This BytesStore as a DebugString.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String toDebugString(long maxLength) {
|
|
||||||
return BytesInternal.toDebugString(this, maxLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the underlying BytesStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
default BytesStore bytesStore() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a portion of a BytesStore matches this one.
|
|
||||||
*
|
|
||||||
* @param bytesStore to match against
|
|
||||||
* @param length to match.
|
|
||||||
* @return true if the bytes up to min(length, this.length(), bytesStore.length()) matched.
|
|
||||||
*/
|
|
||||||
default boolean equalBytes( BytesStore bytesStore, long length)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return length == 8 && bytesStore.length() >= 8
|
|
||||||
? readLong(readPosition()) == bytesStore.readLong(bytesStore.readPosition())
|
|
||||||
: BytesInternal.equalBytesAny(this, bytesStore, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the bytes sum of the readable bytes.
|
|
||||||
*
|
|
||||||
* @return unsigned byte sum.
|
|
||||||
*/
|
|
||||||
default int byteCheckSum() throws IORuntimeException {
|
|
||||||
return byteCheckSum(readPosition(), readLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
default int byteCheckSum(long start, long end) {
|
|
||||||
int sum = 0;
|
|
||||||
for (long i = start; i < end; i++) {
|
|
||||||
sum += readByte(i);
|
|
||||||
}
|
|
||||||
return sum & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the BytesStore end with a character?
|
|
||||||
*
|
|
||||||
* @param c to look for
|
|
||||||
* @return true if its the last character.
|
|
||||||
*/
|
|
||||||
default boolean endsWith(char c) {
|
|
||||||
try {
|
|
||||||
return readRemaining() > 0 && readUnsignedByte(readLimit() - 1) == c;
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the BytesStore start with a character?
|
|
||||||
*
|
|
||||||
* @param c to look for
|
|
||||||
* @return true if its the last character.
|
|
||||||
*/
|
|
||||||
default boolean startsWith(char c) {
|
|
||||||
try {
|
|
||||||
return readRemaining() > 0 && readUnsignedByte(readPosition()) == c;
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare the contents of the BytesStores.
|
|
||||||
*
|
|
||||||
* @param bytesStore to compare with
|
|
||||||
* @return true if they contain the same data.
|
|
||||||
*/
|
|
||||||
default boolean contentEquals( BytesStore bytesStore) {
|
|
||||||
return BytesInternal.contentEqual(this, bytesStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean startsWith( BytesStore bytesStore) {
|
|
||||||
return BytesInternal.startsWith(this, bytesStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default String to8bitString() throws IllegalArgumentException {
|
|
||||||
return BytesInternal.to8bitString(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a <i>not</i> atomic add and get operation for an unsigned byte value. This method
|
|
||||||
* <i>does not</i> check for unsigned byte overflow.
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
*/
|
|
||||||
default int addAndGetUnsignedByteNotAtomic(long offset, int adding) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
int r = (readUnsignedByte(offset) + adding) & 0xFF;
|
|
||||||
writeByte(offset, (byte) r);
|
|
||||||
return r;
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a <i>not</i> atomic add and get operation for a short value.
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
*/
|
|
||||||
default short addAndGetShortNotAtomic(long offset, short adding) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
short r = (short) (readShort(offset) + adding);
|
|
||||||
writeByte(offset, r);
|
|
||||||
return r;
|
|
||||||
} catch (BufferOverflowException | IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a <i>not</i> atomic add and get operation for an int value.
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
*/
|
|
||||||
default int addAndGetIntNotAtomic(long offset, int adding) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
int r = readInt(offset) + adding;
|
|
||||||
writeInt(offset, r);
|
|
||||||
return r;
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a <i>not</i> atomic add and get operation for a float value.
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
*/
|
|
||||||
default double addAndGetDoubleNotAtomic(long offset, double adding) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
double r = readDouble(offset) + adding;
|
|
||||||
writeDouble(offset, r);
|
|
||||||
return r;
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a <i>not</i> atomic add and get operation for a float value.
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
*/
|
|
||||||
default float addAndGetFloatNotAtomic(long offset, float adding) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
float r = readFloat(offset) + adding;
|
|
||||||
writeFloat(offset, r);
|
|
||||||
return r;
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void move(long from, long to, long length) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a value which is not smaller.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param atLeast value it is at least.
|
|
||||||
*/
|
|
||||||
default void writeMaxLong(long offset, long atLeast) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
for (; ; ) {
|
|
||||||
long v = readVolatileLong(offset);
|
|
||||||
if (v >= atLeast)
|
|
||||||
return;
|
|
||||||
if (compareAndSwapLong(offset, v, atLeast))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a value which is not smaller.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param atLeast value it is at least.
|
|
||||||
*/
|
|
||||||
default void writeMaxInt(long offset, int atLeast) throws BufferUnderflowException {
|
|
||||||
try {
|
|
||||||
for (; ; ) {
|
|
||||||
int v = readVolatileInt(offset);
|
|
||||||
if (v >= atLeast)
|
|
||||||
return;
|
|
||||||
if (compareAndSwapInt(offset, v, atLeast))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean isEmpty() {
|
|
||||||
return readRemaining() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void cipher( Cipher cipher, Bytes outBytes, ByteBuffer using1, ByteBuffer using2) throws IllegalStateException {
|
|
||||||
long readPos = outBytes.readPosition();
|
|
||||||
try {
|
|
||||||
long writePos = outBytes.writePosition();
|
|
||||||
BytesStore inBytes;
|
|
||||||
long size = readRemaining();
|
|
||||||
if (this.isDirectMemory()) {
|
|
||||||
inBytes = this;
|
|
||||||
} else {
|
|
||||||
inBytes = NativeBytesStore.nativeStore(size);
|
|
||||||
this.copyTo(inBytes);
|
|
||||||
}
|
|
||||||
BytesInternal.assignBytesStoreToByteBuffer(inBytes, using1);
|
|
||||||
int outputSize = cipher.getOutputSize(Math.toIntExact(size));
|
|
||||||
outBytes.ensureCapacity(writePos + outputSize);
|
|
||||||
outBytes.readPositionRemaining(writePos, outputSize);
|
|
||||||
BytesInternal.assignBytesStoreToByteBuffer(outBytes, using2);
|
|
||||||
int len = cipher.update(using1, using2);
|
|
||||||
len += cipher.doFinal(using1, using2);
|
|
||||||
assert len == using2.position();
|
|
||||||
outBytes.writePosition(writePos + using2.position());
|
|
||||||
|
|
||||||
} catch ( Exception e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
outBytes.readPosition(readPos);
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
//noinspection ThrowFromFinallyBlock
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default void cipher( Cipher cipher, Bytes outBytes) throws IllegalStateException {
|
|
||||||
cipher(cipher, outBytes, BytesInternal.BYTE_BUFFER_TL.get(), BytesInternal.BYTE_BUFFER2_TL.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether this BytesStore is writable.
|
|
||||||
*/
|
|
||||||
default boolean readWrite() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BytesTextMethodTester<T> {
|
|
||||||
private final String input;
|
|
||||||
private final Class<T> outputClass;
|
|
||||||
private final String output;
|
|
||||||
private final Function<T, Object> componentFunction;
|
|
||||||
|
|
||||||
private String setup;
|
|
||||||
private Function<String, String> afterRun;
|
|
||||||
|
|
||||||
private String expected;
|
|
||||||
private String actual;
|
|
||||||
|
|
||||||
public BytesTextMethodTester(String input, Function<T, Object> componentFunction, Class<T> outputClass, String output) {
|
|
||||||
this.input = input;
|
|
||||||
this.outputClass = outputClass;
|
|
||||||
this.output = output;
|
|
||||||
this.componentFunction = componentFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String setup() {
|
|
||||||
return setup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public BytesTextMethodTester setup(String setup) {
|
|
||||||
this.setup = setup;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Function<String, String> afterRun() {
|
|
||||||
return afterRun;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public BytesTextMethodTester afterRun(Function<String, String> afterRun) {
|
|
||||||
this.afterRun = afterRun;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public BytesTextMethodTester run() throws IOException {
|
|
||||||
|
|
||||||
Bytes<?> bytes2 = new HexDumpBytes();
|
|
||||||
T writer = bytes2.bytesMethodWriter(outputClass);
|
|
||||||
|
|
||||||
Object component = componentFunction.apply(writer);
|
|
||||||
Object[] components = component instanceof Object[]
|
|
||||||
? (Object[]) component
|
|
||||||
: new Object[]{component};
|
|
||||||
|
|
||||||
if (setup != null) {
|
|
||||||
Bytes bytes0 = HexDumpBytes.fromText(BytesUtil.readFile(setup));
|
|
||||||
|
|
||||||
BytesMethodReader reader0 = bytes0.bytesMethodReaderBuilder()
|
|
||||||
.defaultParselet(this::unknownMessageId)
|
|
||||||
.build(components);
|
|
||||||
while (reader0.readOne()) {
|
|
||||||
bytes2.clear();
|
|
||||||
}
|
|
||||||
bytes2.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// expected
|
|
||||||
expected = BytesUtil.readFile(output).toString().trim().replace("\r", "");
|
|
||||||
|
|
||||||
Bytes text = BytesUtil.readFile(input);
|
|
||||||
for (String text2 : text.toString().split("###[^\n]*\n")) {
|
|
||||||
if (text2.trim().length() <= 0)
|
|
||||||
continue;
|
|
||||||
Bytes bytes = HexDumpBytes.fromText(text2);
|
|
||||||
|
|
||||||
BytesMethodReader reader = bytes.bytesMethodReaderBuilder()
|
|
||||||
.defaultParselet(this::unknownMessageId)
|
|
||||||
.build(components);
|
|
||||||
|
|
||||||
while (reader.readOne()) {
|
|
||||||
if (bytes.readRemaining() > 1)
|
|
||||||
bytes2.comment("## End Of Message");
|
|
||||||
}
|
|
||||||
bytes.releaseLast();
|
|
||||||
bytes2.comment("## End Of Block");
|
|
||||||
}
|
|
||||||
bytes2.comment("## End Of Test");
|
|
||||||
|
|
||||||
actual = bytes2.toHexString().trim();
|
|
||||||
if (afterRun != null) {
|
|
||||||
expected = afterRun.apply(expected);
|
|
||||||
actual = afterRun.apply(actual);
|
|
||||||
}
|
|
||||||
bytes2.releaseLast();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unknownMessageId(long id, BytesIn b) {
|
|
||||||
Jvm.warn().on(getClass(), "Unknown message id " + Long.toHexString(id));
|
|
||||||
b.readPosition(b.readLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String expected() {
|
|
||||||
return expected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String actual() {
|
|
||||||
return actual;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,331 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.ClassLocal;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.UnsafeMemory;
|
|
||||||
import net.openhft.chronicle.core.io.AbstractReferenceCounted;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.IOTools;
|
|
||||||
import net.openhft.chronicle.core.util.StringUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.core.io.IOTools.*;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public enum BytesUtil {
|
|
||||||
;
|
|
||||||
private static final int[] NO_INTS = {};
|
|
||||||
private static final ClassLocal<int[]> TRIVIALLY_COPYABLE = ClassLocal.withInitial(BytesUtil::isTriviallyCopyable0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the whole class trivially copyable
|
|
||||||
*
|
|
||||||
* @param clazz to check
|
|
||||||
* @return true if the whole class is trivially copyable
|
|
||||||
*/
|
|
||||||
public static boolean isTriviallyCopyable(Class clazz) {
|
|
||||||
return TRIVIALLY_COPYABLE.get(clazz).length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int[] isTriviallyCopyable0(Class clazz) {
|
|
||||||
if (clazz.isArray()) {
|
|
||||||
Class componentType = clazz.getComponentType();
|
|
||||||
if (componentType.isPrimitive())
|
|
||||||
return new int[]{UnsafeMemory.UNSAFE.arrayBaseOffset(clazz)};
|
|
||||||
return NO_INTS;
|
|
||||||
}
|
|
||||||
List<Field> fields = new ArrayList<>();
|
|
||||||
while (clazz != null && clazz != Object.class) {
|
|
||||||
Collections.addAll(fields, clazz.getDeclaredFields());
|
|
||||||
clazz = clazz.getSuperclass();
|
|
||||||
}
|
|
||||||
int min = Integer.MAX_VALUE;
|
|
||||||
int max = Integer.MIN_VALUE;
|
|
||||||
for (Field field : fields) {
|
|
||||||
int modifiers = field.getModifiers();
|
|
||||||
if (Modifier.isStatic(modifiers))
|
|
||||||
continue;
|
|
||||||
long offset2 = UnsafeMemory.UNSAFE.objectFieldOffset(field);
|
|
||||||
int size = sizeOf(field.getType());
|
|
||||||
min = (int) Math.min(min, offset2);
|
|
||||||
max = (int) Math.max(max, offset2 + size);
|
|
||||||
if (Modifier.isTransient(modifiers))
|
|
||||||
return NO_INTS;
|
|
||||||
if (!field.getType().isPrimitive())
|
|
||||||
return NO_INTS;
|
|
||||||
}
|
|
||||||
return new int[]{min, max};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Are all the fields in the range given trivially copyable
|
|
||||||
*
|
|
||||||
* @param clazz to check
|
|
||||||
* @return true if the fields in range are trivially copyable.
|
|
||||||
*/
|
|
||||||
public static boolean isTriviallyCopyable(Class clazz, int offset, int length) {
|
|
||||||
int[] ints = TRIVIALLY_COPYABLE.get(clazz);
|
|
||||||
if (ints.length == 0)
|
|
||||||
return false;
|
|
||||||
return offset >= ints[0] && (ints.length == 1 || offset + length <= ints[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int[] triviallyCopyableRange(Class clazz) {
|
|
||||||
return TRIVIALLY_COPYABLE.get(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int sizeOf(Class<?> type) {
|
|
||||||
return type == boolean.class || type == byte.class ? 1
|
|
||||||
: type == short.class || type == char.class ? 2
|
|
||||||
: type == int.class || type == float.class ? 4
|
|
||||||
: type == long.class || type == double.class ? 8
|
|
||||||
: Unsafe.ARRAY_OBJECT_INDEX_SCALE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String findFile( String name) throws FileNotFoundException {
|
|
||||||
File file = new File(name);
|
|
||||||
URL url = null;
|
|
||||||
if (!file.exists()) {
|
|
||||||
url = urlFor(name);
|
|
||||||
String file2 = url.getFile()
|
|
||||||
.replace("target/test-classes", "src/test/resources");
|
|
||||||
file = new File(file2);
|
|
||||||
}
|
|
||||||
if (!file.exists())
|
|
||||||
throw new FileNotFoundException(name);
|
|
||||||
return file.getAbsolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bytes readFile( String name) throws IOException {
|
|
||||||
if (name.startsWith("=")) {
|
|
||||||
return Bytes.from(name.substring(1));
|
|
||||||
}
|
|
||||||
File file = new File(name);
|
|
||||||
URL url = null;
|
|
||||||
if (!file.exists()) {
|
|
||||||
url = urlFor(name);
|
|
||||||
file = new File(url.getFile());
|
|
||||||
}
|
|
||||||
return // name.endsWith(".gz") || !file.exists() || OS.isWindows() ?
|
|
||||||
Bytes.wrapForRead(readAsBytes(url == null ? new FileInputStream(file) : open(url)));
|
|
||||||
//: MappedFile.readOnly(file).acquireBytesForRead(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeFile(String file, Bytes<byte[]> bytes) throws IOException {
|
|
||||||
try (OutputStream os = new FileOutputStream(file)) {
|
|
||||||
os.write(bytes.underlyingObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean bytesEqual(
|
|
||||||
RandomDataInput a, long offset,
|
|
||||||
RandomDataInput second, long secondOffset, long len)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
long i = 0;
|
|
||||||
while (len - i >= 8L) {
|
|
||||||
if (a.readLong(offset + i) != second.readLong(secondOffset + i))
|
|
||||||
return false;
|
|
||||||
i += 8L;
|
|
||||||
}
|
|
||||||
if (len - i >= 4L) {
|
|
||||||
if (a.readInt(offset + i) != second.readInt(secondOffset + i))
|
|
||||||
return false;
|
|
||||||
i += 4L;
|
|
||||||
}
|
|
||||||
if (len - i >= 2L) {
|
|
||||||
if (a.readShort(offset + i) != second.readShort(secondOffset + i))
|
|
||||||
return false;
|
|
||||||
i += 2L;
|
|
||||||
}
|
|
||||||
if (i < len)
|
|
||||||
return a.readByte(offset + i) == second.readByte(secondOffset + i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean bytesEqual( CharSequence cs, RandomDataInput bs, long offset, int length) {
|
|
||||||
if (cs == null || cs.length() != length)
|
|
||||||
return false;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
if (cs.charAt(i) != bs.readUnsignedByte(offset + i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean equals(Object o1, Object o2) {
|
|
||||||
if (o1 == o2) return true;
|
|
||||||
if (o1 instanceof CharSequence && o2 instanceof CharSequence)
|
|
||||||
return StringUtils.isEqual((CharSequence) o1, (CharSequence) o2);
|
|
||||||
return o1 != null && o1.equals(o2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int asInt( String str) {
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(str.getBytes(StandardCharsets.ISO_8859_1)).order(ByteOrder.nativeOrder());
|
|
||||||
return bb.getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int stopBitLength(long n) {
|
|
||||||
if ((n & ~0x7F) == 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((n & ~0x3FFF) == 0) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return BytesInternal.stopBitLength0(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static char[] toCharArray( Bytes bytes) {
|
|
||||||
final char[] chars = new char[Maths.toUInt31(bytes.readRemaining())];
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes.readRemaining(); i++) {
|
|
||||||
chars[i] = (char) bytes.readUnsignedByte(i + bytes.readPosition());
|
|
||||||
}
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static char[] toCharArray( Bytes bytes, long position, int length) {
|
|
||||||
final char[] chars = new char[length];
|
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
chars[j++] = (char) bytes.readUnsignedByte(position + i);
|
|
||||||
}
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long readStopBit( StreamingDataInput in) throws IORuntimeException {
|
|
||||||
return BytesInternal.readStopBit(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeStopBit( StreamingDataOutput out, long n) {
|
|
||||||
BytesInternal.writeStopBit(out, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parseUtf8(
|
|
||||||
StreamingDataInput in, Appendable appendable, int utflen)
|
|
||||||
throws UTFDataFormatRuntimeException {
|
|
||||||
BytesInternal.parseUtf8(in, appendable, true, utflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void appendUtf8( StreamingDataOutput out, CharSequence cs) {
|
|
||||||
BytesInternal.appendUtf8(out, cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
// used by Chronicle FIX.
|
|
||||||
public static void appendBytesFromStart( Bytes bytes, long startPosition, StringBuilder sb) {
|
|
||||||
try {
|
|
||||||
BytesInternal.parse8bit(startPosition, bytes, sb, (int) (bytes.readPosition() - startPosition));
|
|
||||||
sb.append('\u2016');
|
|
||||||
sb.append(bytes);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IORuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readMarshallable( ReadBytesMarshallable marshallable, BytesIn bytes) {
|
|
||||||
BytesMarshaller.BYTES_MARSHALLER_CL.get(marshallable.getClass())
|
|
||||||
.readMarshallable(marshallable, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeMarshallable( WriteBytesMarshallable marshallable, BytesOut bytes) {
|
|
||||||
BytesMarshaller.BYTES_MARSHALLER_CL.get(marshallable.getClass())
|
|
||||||
.writeMarshallable(marshallable, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
public static long utf8Length( CharSequence toWrite) {
|
|
||||||
return AppendableUtil.findUtf8Length(toWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String asString(String s, Throwable t) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
sw.append(s).append("\n");
|
|
||||||
t.printStackTrace(new PrintWriter(sw));
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// calls the BackgroundResourceReleaser and AbstractCloseable.assertCloseableClose first.
|
|
||||||
public static void checkRegisteredBytes() {
|
|
||||||
AbstractReferenceCounted.assertReferencesReleased();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean byteToBoolean(byte b) {
|
|
||||||
return b != 0 && b != 'N' && b != 'n';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long roundUpTo64ByteAlign(long x) {
|
|
||||||
return (x + 63L) & ~63L;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long roundUpTo8ByteAlign(long x) {
|
|
||||||
return (x + 7L) & ~7L;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void read8ByteAlignPadding(Bytes<?> bytes) {
|
|
||||||
bytes.readPosition(roundUpTo8ByteAlign(bytes.readPosition()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void write8ByteAlignPadding(Bytes<?> bytes) {
|
|
||||||
long start = bytes.writePosition();
|
|
||||||
long end = roundUpTo8ByteAlign(start);
|
|
||||||
bytes.writePosition(end);
|
|
||||||
bytes.zeroOut(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toDebugString( RandomDataInput bytes, long start, long maxLength) {
|
|
||||||
BytesStore bytes2 = bytes.subBytes(start, maxLength);
|
|
||||||
return bytes2.toDebugString(maxLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
public static boolean unregister(BytesStore bs) {
|
|
||||||
IOTools.unmonitor(bs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class WarnUncheckedElasticBytes {
|
|
||||||
static {
|
|
||||||
Jvm.debug().on(WarnUncheckedElasticBytes.class, "Wrapping elastic bytes with unchecked() will require calling ensureCapacity() as needed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void warn() {
|
|
||||||
// static block does the work.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.annotation.DontChain;
|
|
||||||
|
|
||||||
@DontChain
|
|
||||||
public interface CommonMarshallable {
|
|
||||||
/**
|
|
||||||
* @return whether this message should be written as self describing
|
|
||||||
*/
|
|
||||||
default boolean usesSelfDescribingMessage() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* thrown when the TcpChannelHub drops its connection to the server
|
|
||||||
*/
|
|
||||||
// TODO Move to network where it is used.
|
|
||||||
public class ConnectionDroppedException extends IORuntimeException {
|
|
||||||
public ConnectionDroppedException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConnectionDroppedException(Throwable e) {
|
|
||||||
super(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConnectionDroppedException(String s, Throwable e) {
|
|
||||||
super(s, e);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marker interface for implementors of {@link Byteable} that indicates
|
|
||||||
* that size requirements can only be calculated on a user-supplied instance.
|
|
||||||
*/
|
|
||||||
public interface DynamicallySized {
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.BinaryWireCode.*;
|
|
||||||
|
|
||||||
public class GuardedNativeBytes<Underlying> extends NativeBytes<Underlying> {
|
|
||||||
static final byte BYTE_T = (byte) INT8;
|
|
||||||
static final byte SHORT_T = (byte) INT16;
|
|
||||||
static final byte INT_T = (byte) INT32;
|
|
||||||
static final byte LONG_T = (byte) INT64;
|
|
||||||
static final byte STOP_T = (byte) STOP_BIT;
|
|
||||||
static final byte FLOAT_T = (byte) FLOAT32;
|
|
||||||
static final byte DOUBLE_T = (byte) FLOAT64;
|
|
||||||
|
|
||||||
private static final String[] STRING_FOR_CODE = _stringForCode(GuardedNativeBytes.class);
|
|
||||||
|
|
||||||
public GuardedNativeBytes( BytesStore store, long capacity) throws IllegalStateException {
|
|
||||||
super(store, capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeByte(byte i8) throws BufferOverflowException {
|
|
||||||
super.writeByte(BYTE_T);
|
|
||||||
return super.writeByte(i8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> rawWriteByte(byte i8) throws BufferOverflowException {
|
|
||||||
return super.writeByte(i8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> rawWriteInt(int i) throws BufferOverflowException {
|
|
||||||
return super.writeInt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte() {
|
|
||||||
expectByte(BYTE_T);
|
|
||||||
return super.readByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte rawReadByte() {
|
|
||||||
return super.readByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int rawReadInt() {
|
|
||||||
return super.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readUnsignedByte() {
|
|
||||||
expectByte(BYTE_T);
|
|
||||||
return super.readUnsignedByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeShort(short i16) throws BufferOverflowException {
|
|
||||||
super.writeByte(SHORT_T);
|
|
||||||
return super.writeShort(i16);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort() throws BufferUnderflowException {
|
|
||||||
expectByte(SHORT_T);
|
|
||||||
return super.readShort();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeStopBit(char x) throws BufferOverflowException {
|
|
||||||
super.writeByte(STOP_T);
|
|
||||||
return super.writeStopBit(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeStopBit(long x) throws BufferOverflowException {
|
|
||||||
super.writeByte(STOP_T);
|
|
||||||
return super.writeStopBit(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readStopBit() throws IORuntimeException {
|
|
||||||
expectByte(STOP_T);
|
|
||||||
return super.readStopBit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public char readStopBitChar() throws IORuntimeException {
|
|
||||||
expectByte(STOP_T);
|
|
||||||
return super.readStopBitChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeInt(int i) throws BufferOverflowException {
|
|
||||||
super.writeByte(INT_T);
|
|
||||||
return super.writeInt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readInt() throws BufferUnderflowException {
|
|
||||||
expectByte(INT_T);
|
|
||||||
return super.readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes writeLong(long i64) throws BufferOverflowException {
|
|
||||||
super.writeByte(LONG_T);
|
|
||||||
return super.writeLong(i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readLong() throws BufferUnderflowException {
|
|
||||||
expectByte(LONG_T);
|
|
||||||
return super.readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeFloat(float f) throws BufferOverflowException {
|
|
||||||
super.writeByte(FLOAT_T);
|
|
||||||
return super.writeFloat(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat() throws BufferUnderflowException {
|
|
||||||
expectByte(FLOAT_T);
|
|
||||||
return super.readFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeDouble(double d) throws BufferOverflowException {
|
|
||||||
super.writeByte(DOUBLE_T);
|
|
||||||
return super.writeDouble(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble() throws BufferUnderflowException {
|
|
||||||
expectByte(DOUBLE_T);
|
|
||||||
return super.readDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expectByte(byte expected) {
|
|
||||||
byte type = super.readByte();
|
|
||||||
if (type != expected)
|
|
||||||
throw new IllegalStateException("Expected " + STRING_FOR_CODE[expected & 0xFF]
|
|
||||||
+ " but was " + STRING_FOR_CODE[type & 0xFF]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,402 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.util.DecoratedBufferOverflowException;
|
|
||||||
import net.openhft.chronicle.bytes.util.DecoratedBufferUnderflowException;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.Memory;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for Heap ByteBuffers and arrays.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("restriction")
|
|
||||||
public class HeapBytesStore<Underlying>
|
|
||||||
extends AbstractBytesStore<HeapBytesStore<Underlying>, Underlying> {
|
|
||||||
|
|
||||||
private static final Memory MEMORY = OS.memory();
|
|
||||||
|
|
||||||
private final Object realUnderlyingObject;
|
|
||||||
private final int dataOffset;
|
|
||||||
private final long capacity;
|
|
||||||
|
|
||||||
private final Underlying underlyingObject;
|
|
||||||
|
|
||||||
private HeapBytesStore( ByteBuffer byteBuffer) {
|
|
||||||
super(false);
|
|
||||||
//noinspection unchecked
|
|
||||||
this.underlyingObject = (Underlying) byteBuffer;
|
|
||||||
this.realUnderlyingObject = byteBuffer.array();
|
|
||||||
this.dataOffset = Jvm.arrayByteBaseOffset() + byteBuffer.arrayOffset();
|
|
||||||
this.capacity = byteBuffer.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
private HeapBytesStore( byte [] byteArray) {
|
|
||||||
super(false);
|
|
||||||
//noinspection unchecked
|
|
||||||
this.underlyingObject = (Underlying) byteArray;
|
|
||||||
this.realUnderlyingObject = byteArray;
|
|
||||||
this.dataOffset = Jvm.arrayByteBaseOffset();
|
|
||||||
this.capacity = byteArray.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by Chronicle-Map.
|
|
||||||
|
|
||||||
public static HeapBytesStore<byte[]> wrap( byte[] byteArray) {
|
|
||||||
return new HeapBytesStore<>(byteArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by Chronicle-Map.
|
|
||||||
|
|
||||||
public static HeapBytesStore<ByteBuffer> wrap( ByteBuffer bb) {
|
|
||||||
return new HeapBytesStore<>(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirectMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(long from, long to, long length) {
|
|
||||||
if (from < 0 || to < 0) throw new BufferUnderflowException();
|
|
||||||
//noinspection SuspiciousSystemArraycopy
|
|
||||||
System.arraycopy(realUnderlyingObject, Maths.toUInt31(from), realUnderlyingObject, Maths.toUInt31(to), Maths.toUInt31(length));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
try {
|
|
||||||
return BytesInternal.toString(this);
|
|
||||||
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
return e.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore<HeapBytesStore<Underlying>, Underlying> copy() {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performRelease() {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Underlying underlyingObject() {
|
|
||||||
return underlyingObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value) {
|
|
||||||
return MEMORY.compareAndSwapInt(realUnderlyingObject, dataOffset + offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testAndSetInt(long offset, int expected, int value) {
|
|
||||||
MEMORY.testAndSetInt(realUnderlyingObject, dataOffset + offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value) {
|
|
||||||
return MEMORY.compareAndSwapLong(
|
|
||||||
realUnderlyingObject, dataOffset + offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 1);
|
|
||||||
return MEMORY.readByte(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 2);
|
|
||||||
return MEMORY.readShort(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readInt(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 4);
|
|
||||||
return MEMORY.readInt(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readLong(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 8);
|
|
||||||
return MEMORY.readLong(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 4);
|
|
||||||
return MEMORY.readFloat(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 8);
|
|
||||||
return MEMORY.readDouble(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readVolatileByte(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 1);
|
|
||||||
return MEMORY.readVolatileByte(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readVolatileShort(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 2);
|
|
||||||
return MEMORY.readVolatileShort(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readVolatileInt(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 4);
|
|
||||||
return MEMORY.readVolatileInt(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readVolatileLong(long offset) throws BufferUnderflowException {
|
|
||||||
checkOffset(offset, 8);
|
|
||||||
return MEMORY.readVolatileLong(realUnderlyingObject, dataOffset + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeByte(long offset, byte b)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 1);
|
|
||||||
MEMORY.writeByte(realUnderlyingObject, dataOffset + offset, b);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeShort(long offset, short i16)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 2);
|
|
||||||
MEMORY.writeShort(realUnderlyingObject, dataOffset + offset, i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeInt(long offset, int i32)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
MEMORY.writeInt(realUnderlyingObject, dataOffset + offset, i32);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeOrderedInt(long offset, int i32)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
MEMORY.writeOrderedInt(realUnderlyingObject, dataOffset + offset, i32);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeLong(long offset, long i64)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
MEMORY.writeLong(realUnderlyingObject, dataOffset + offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeOrderedLong(long offset, long i)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
MEMORY.writeOrderedLong(realUnderlyingObject, dataOffset + offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeFloat(long offset, float f)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
MEMORY.writeFloat(realUnderlyingObject, dataOffset + offset, f);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeDouble(long offset, double d)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
MEMORY.writeDouble(realUnderlyingObject, dataOffset + offset, d);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeVolatileByte(long offset, byte i8)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 1);
|
|
||||||
MEMORY.writeVolatileByte(realUnderlyingObject, dataOffset + offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeVolatileShort(long offset, short i16)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 2);
|
|
||||||
MEMORY.writeVolatileShort(realUnderlyingObject, dataOffset + offset, i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeVolatileInt(long offset, int i32)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
MEMORY.writeVolatileInt(realUnderlyingObject, dataOffset + offset, i32);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> writeVolatileLong(long offset, long i64)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
MEMORY.writeVolatileLong(realUnderlyingObject, dataOffset + offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> write(
|
|
||||||
long offsetInRDO, byte[] bytes, int offset, int length) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offsetInRDO, length);
|
|
||||||
MEMORY.copyMemory(
|
|
||||||
bytes, offset, realUnderlyingObject, this.dataOffset + offsetInRDO, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(
|
|
||||||
long offsetInRDO, ByteBuffer bytes, int offset, int length) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offsetInRDO, length);
|
|
||||||
assert realUnderlyingObject == null || dataOffset >= (Jvm.is64bit() ? 12 : 8);
|
|
||||||
if (bytes.isDirect()) {
|
|
||||||
MEMORY.copyMemory(Jvm.address(bytes), realUnderlyingObject,
|
|
||||||
this.dataOffset + offsetInRDO, length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
MEMORY.copyMemory(bytes.array(), offset, realUnderlyingObject,
|
|
||||||
this.dataOffset + offsetInRDO, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HeapBytesStore<Underlying> write(long writeOffset,
|
|
||||||
RandomDataInput bytes, long readOffset, long length) {
|
|
||||||
long i;
|
|
||||||
for (i = 0; i < length - 7; i += 8) {
|
|
||||||
long x = bytes.readLong(readOffset + i);
|
|
||||||
writeLong(writeOffset + i, x);
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
byte x = bytes.readByte(readOffset + i);
|
|
||||||
writeByte(writeOffset + i, x);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForRead(long offset) throws UnsupportedOperationException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWrite(long offset) throws UnsupportedOperationException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWritePosition() throws UnsupportedOperationException, BufferOverflowException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeRead(long position, long address, long size) {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeWrite(long address, long position, long size) {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return obj instanceof BytesStore && BytesInternal.contentEqual(this, (BytesStore) obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sharedMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkOffset(long offset, int size) throws BufferUnderflowException {
|
|
||||||
checkBounds(offset, size, DecoratedBufferUnderflowException::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeCheckOffset(long offset, int size) throws BufferOverflowException {
|
|
||||||
checkBounds(offset, size, DecoratedBufferOverflowException::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkBounds(final long offset, final int size,
|
|
||||||
final Function<String, RuntimeException> exceptionFunction) {
|
|
||||||
if (offset < start() || offset + size > capacity) {
|
|
||||||
throw exceptionFunction.apply(
|
|
||||||
String.format("Offset: %d, start: %d, size: %d, capacity: %d",
|
|
||||||
offset, start(), size, capacity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface Invocation {
|
|
||||||
Object invoke(Method m, Object o, Object[] args) throws InvocationTargetException;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BytesStore to wrap memory mapped data.
|
|
||||||
*/
|
|
||||||
public class MappedBytesStore extends NativeBytesStore<Void> {
|
|
||||||
private final MappedFile mappedFile;
|
|
||||||
private final long start;
|
|
||||||
private final long safeLimit;
|
|
||||||
|
|
||||||
protected MappedBytesStore(ReferenceOwner owner, MappedFile mappedFile, long start, long address, long capacity, long safeCapacity) throws IllegalStateException {
|
|
||||||
super(address, start + capacity, new OS.Unmapper(address, capacity), false);
|
|
||||||
this.mappedFile = mappedFile;
|
|
||||||
this.start = start;
|
|
||||||
this.safeLimit = start + safeCapacity;
|
|
||||||
reserveTransfer(INIT, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the capacity of the underlying file
|
|
||||||
* This can differ from the exposed capacity() of this bytes store (which has been page aligned)
|
|
||||||
*
|
|
||||||
* @return - capacity of the underlying file
|
|
||||||
*/
|
|
||||||
public long underlyingCapacity() {
|
|
||||||
return mappedFile.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Void> bytesForRead() throws IllegalStateException {
|
|
||||||
try {
|
|
||||||
return new VanillaBytes<Void>(this)
|
|
||||||
.readLimit(writeLimit())
|
|
||||||
.readPosition(start());
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VanillaBytes<Void> bytesForWrite() throws IllegalStateException {
|
|
||||||
return new VanillaBytes<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset) {
|
|
||||||
return start <= offset && offset < safeLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset, long buffer) {
|
|
||||||
// this is correct that it uses the maximumLimit, yes it is different than the method above.
|
|
||||||
return start <= offset && offset + buffer < limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long safeLimit() {
|
|
||||||
return safeLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte(long offset) {
|
|
||||||
return memory.readByte(address - start + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeOrderedInt(long offset, int i) {
|
|
||||||
memory.writeOrderedInt(address - start + offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long translate(long offset) {
|
|
||||||
assert offset >= start;
|
|
||||||
assert offset < limit;
|
|
||||||
|
|
||||||
return offset - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long start() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readPosition() {
|
|
||||||
return start();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MappedBytesStoreFactory {
|
|
||||||
|
|
||||||
MappedBytesStore create(ReferenceOwner owner, MappedFile mappedFile, long start, long address, long capacity, long safeCapacity);
|
|
||||||
}
|
|
|
@ -1,541 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.CleaningRandomAccessFile;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.io.AbstractCloseableReferenceCounted;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import net.openhft.chronicle.core.onoes.Slf4jExceptionHandler;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.channels.ClosedByInterruptException;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.nio.channels.FileChannel.MapMode;
|
|
||||||
import java.nio.channels.FileLock;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.core.io.Closeable.closeQuietly;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A memory mapped files which can be randomly accessed in chunks. It has overlapping regions to
|
|
||||||
* avoid wasting bytes at the end of chunks.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked", "restriction"})
|
|
||||||
public class MappedFile extends AbstractCloseableReferenceCounted {
|
|
||||||
static final boolean RETAIN = Jvm.getBoolean("mappedFile.retain");
|
|
||||||
private static final long DEFAULT_CAPACITY = 128L << 40;
|
|
||||||
|
|
||||||
|
|
||||||
private final RandomAccessFile raf;
|
|
||||||
private final FileChannel fileChannel;
|
|
||||||
private final long chunkSize;
|
|
||||||
private final long overlapSize;
|
|
||||||
private final List<MappedBytesStore> stores = new ArrayList<>();
|
|
||||||
private final long capacity;
|
|
||||||
|
|
||||||
private final File file;
|
|
||||||
private final String canonicalPath;
|
|
||||||
private final boolean readOnly;
|
|
||||||
private NewChunkListener newChunkListener = MappedFile::logNewChunk;
|
|
||||||
|
|
||||||
protected MappedFile( final File file,
|
|
||||||
final RandomAccessFile raf,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize,
|
|
||||||
final long capacity,
|
|
||||||
final boolean readOnly) {
|
|
||||||
this.file = file;
|
|
||||||
try {
|
|
||||||
this.canonicalPath = file.getCanonicalPath().intern();
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new IllegalStateException("Unable to obtain the canonical path for " + file.getAbsolutePath(), ioe);
|
|
||||||
}
|
|
||||||
this.raf = raf;
|
|
||||||
this.fileChannel = raf.getChannel();
|
|
||||||
this.chunkSize = OS.mapAlign(chunkSize);
|
|
||||||
this.overlapSize = overlapSize > 0 && overlapSize < 64 << 10 ? chunkSize : OS.mapAlign(overlapSize);
|
|
||||||
this.capacity = capacity;
|
|
||||||
this.readOnly = readOnly;
|
|
||||||
|
|
||||||
Jvm.doNotCloseOnInterrupt(getClass(), this.fileChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logNewChunk(final String filename,
|
|
||||||
final int chunk,
|
|
||||||
final long delayMicros) {
|
|
||||||
if (delayMicros < 100 || !Jvm.isDebugEnabled(MappedFile.class))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// avoid a GC while trying to memory map.
|
|
||||||
final String message = BytesInternal.acquireStringBuilder()
|
|
||||||
.append("Allocation of ").append(chunk)
|
|
||||||
.append(" chunk in ").append(filename)
|
|
||||||
.append(" took ").append(delayMicros / 1e3).append(" ms.")
|
|
||||||
.toString();
|
|
||||||
Jvm.perf().on(MappedFile.class, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile of( final File file,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize,
|
|
||||||
final boolean readOnly) throws FileNotFoundException {
|
|
||||||
// if (readOnly && OS.isWindows()) {
|
|
||||||
// Jvm.warn().on(MappedFile.class, "Read only mode not supported on Windows, defaulting to read/write");
|
|
||||||
// readOnly = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
RandomAccessFile raf = new CleaningRandomAccessFile(file, readOnly ? "r" : "rw");
|
|
||||||
// try {
|
|
||||||
final long capacity = /*readOnly ? raf.length() : */DEFAULT_CAPACITY;
|
|
||||||
return new MappedFile(file, raf, chunkSize, overlapSize, capacity, readOnly);
|
|
||||||
/*
|
|
||||||
} catch (IOException e) {
|
|
||||||
Closeable.closeQuietly(raf);
|
|
||||||
FileNotFoundException fnfe = new FileNotFoundException("Unable to open " + file);
|
|
||||||
fnfe.initCause(e);
|
|
||||||
throw fnfe;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final File file, final long chunkSize) throws FileNotFoundException {
|
|
||||||
return mappedFile(file, chunkSize, OS.pageSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private void check(Throwable throwable, int[] count) {
|
|
||||||
for (int i = 0; i < stores.size(); i++) {
|
|
||||||
WeakReference<MappedBytesStore> storeRef = stores.get(i);
|
|
||||||
if (storeRef == null)
|
|
||||||
continue;
|
|
||||||
MappedBytesStore mbs = storeRef.get();
|
|
||||||
if (mbs != null && mbs.refCount() > 0) {
|
|
||||||
mbs.releaseLast();
|
|
||||||
throwable.printStackTrace();
|
|
||||||
count[0]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final String filename, final long chunkSize) throws FileNotFoundException {
|
|
||||||
return mappedFile(filename, chunkSize, OS.pageSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final String filename,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize) throws FileNotFoundException {
|
|
||||||
return mappedFile(new File(filename), chunkSize, overlapSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final File file,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize) throws FileNotFoundException {
|
|
||||||
return mappedFile(file, chunkSize, overlapSize, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final File file,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize,
|
|
||||||
final boolean readOnly) throws FileNotFoundException {
|
|
||||||
return MappedFile.of(file, chunkSize, overlapSize, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile readOnly( final File file) throws FileNotFoundException {
|
|
||||||
long chunkSize = file.length();
|
|
||||||
long overlapSize = 0;
|
|
||||||
// Chunks of 4 GB+ not supported on Windows.
|
|
||||||
if (OS.isWindows() && chunkSize > 2L << 30) {
|
|
||||||
chunkSize = 2L << 30;
|
|
||||||
overlapSize = OS.pageSize();
|
|
||||||
}
|
|
||||||
return MappedFile.of(file, chunkSize, overlapSize, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static MappedFile mappedFile( final File file,
|
|
||||||
final long capacity,
|
|
||||||
final long chunkSize,
|
|
||||||
final long overlapSize,
|
|
||||||
final boolean readOnly) throws IOException {
|
|
||||||
final RandomAccessFile raf = new CleaningRandomAccessFile(file, readOnly ? "r" : "rw");
|
|
||||||
// Windows throws an exception when setting the length when you re-open
|
|
||||||
if (raf.length() < capacity)
|
|
||||||
raf.setLength(capacity);
|
|
||||||
return new MappedFile(file, raf, chunkSize, overlapSize, capacity, readOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void warmup() {
|
|
||||||
final List<IOException> errorsDuringWarmup = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
Jvm.setExceptionHandlers(Slf4jExceptionHandler.FATAL, null, null);
|
|
||||||
|
|
||||||
final File file = File.createTempFile("delete_warming_up", "me");
|
|
||||||
file.deleteOnExit();
|
|
||||||
final long mapAlignment = OS.mapAlignment();
|
|
||||||
final int chunks = 64;
|
|
||||||
final int compileThreshold = Jvm.compileThreshold();
|
|
||||||
for (int j = 0; j <= compileThreshold; j += chunks) {
|
|
||||||
try {
|
|
||||||
try ( RandomAccessFile raf = new CleaningRandomAccessFile(file, "rw")) {
|
|
||||||
try (final MappedFile mappedFile = new MappedFile(file, raf, mapAlignment, 0, mapAlignment * chunks, false)) {
|
|
||||||
warmup0(mapAlignment, chunks, mappedFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Thread.yield();
|
|
||||||
} catch (IOException e) {
|
|
||||||
errorsDuringWarmup.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Thread.yield();
|
|
||||||
Files.delete(file.toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
Jvm.resetExceptionHandlers();
|
|
||||||
Jvm.warn().on(MappedFile.class, "Error during warmup", e);
|
|
||||||
} finally {
|
|
||||||
Jvm.resetExceptionHandlers();
|
|
||||||
if (errorsDuringWarmup.size() > 0)
|
|
||||||
Jvm.warn().on(MappedFile.class, errorsDuringWarmup.size() + " errors during warmup: " + errorsDuringWarmup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void warmup0(final long mapAlignment,
|
|
||||||
final int chunks,
|
|
||||||
final MappedFile mappedFile) throws IOException {
|
|
||||||
ReferenceOwner warmup = ReferenceOwner.temporary("warmup");
|
|
||||||
for (int i = 0; i < chunks; i++) {
|
|
||||||
mappedFile.acquireBytesForRead(warmup, i * mapAlignment)
|
|
||||||
.release(warmup);
|
|
||||||
mappedFile.acquireBytesForWrite(warmup, i * mapAlignment)
|
|
||||||
.release(warmup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public File file() {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IllegalStateException if closed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public MappedBytesStore acquireByteStore(
|
|
||||||
ReferenceOwner owner,
|
|
||||||
final long position)
|
|
||||||
throws IOException, IllegalArgumentException, IllegalStateException {
|
|
||||||
return acquireByteStore(owner, position, null, readOnly ? ReadOnlyMappedBytesStore::new : MappedBytesStore::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MappedBytesStore acquireByteStore(
|
|
||||||
ReferenceOwner owner,
|
|
||||||
final long position,
|
|
||||||
BytesStore oldByteStore)
|
|
||||||
throws IOException, IllegalArgumentException, IllegalStateException {
|
|
||||||
return acquireByteStore(owner, position, oldByteStore, readOnly ? ReadOnlyMappedBytesStore::new : MappedBytesStore::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public MappedBytesStore acquireByteStore(
|
|
||||||
ReferenceOwner owner,
|
|
||||||
final long position,
|
|
||||||
BytesStore oldByteStore,
|
|
||||||
final MappedBytesStoreFactory mappedBytesStoreFactory)
|
|
||||||
throws IOException,
|
|
||||||
IllegalArgumentException,
|
|
||||||
IllegalStateException {
|
|
||||||
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (position < 0)
|
|
||||||
throw new IOException("Attempt to access a negative position: " + position);
|
|
||||||
final int chunk = (int) (position / chunkSize);
|
|
||||||
Jvm.safepoint();
|
|
||||||
|
|
||||||
final MappedBytesStore mbs;
|
|
||||||
synchronized (stores) {
|
|
||||||
while (stores.size() <= chunk)
|
|
||||||
stores.add(null);
|
|
||||||
mbs = stores.get(chunk);
|
|
||||||
}
|
|
||||||
if (mbs != null) {
|
|
||||||
// don't reserve it again if we are already holding it.
|
|
||||||
if (mbs == oldByteStore) {
|
|
||||||
return mbs;
|
|
||||||
}
|
|
||||||
if (mbs.tryReserve(owner)) {
|
|
||||||
return mbs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// its important we perform this outside the synchronized below, as this operation can take a while and if synchronized can block slow tailer
|
|
||||||
// from acquiring the next block
|
|
||||||
resizeRafIfTooSmall(chunk);
|
|
||||||
|
|
||||||
synchronized (stores) {
|
|
||||||
|
|
||||||
// We are back, protected by synchronized, and need to
|
|
||||||
// update our view on previous existence (we might have been stalled
|
|
||||||
// for a long time since we last checked dues to resizing and another
|
|
||||||
// thread might have added a MappedByteStore (very unlikely but still possible))
|
|
||||||
final MappedBytesStore mbs1 = stores.get(chunk);
|
|
||||||
if (mbs1 != null && mbs1.tryReserve(owner)) {
|
|
||||||
return mbs1;
|
|
||||||
}
|
|
||||||
// *** THIS CAN TAKE A LONG TIME IF A RESIZE HAS TO OCCUR ***
|
|
||||||
// let double check it to make sure no other thread change it in the meantime.
|
|
||||||
//resizeRafIfTooSmall(chunk);
|
|
||||||
|
|
||||||
final long mappedSize = chunkSize + overlapSize;
|
|
||||||
final MapMode mode = readOnly ? MapMode.READ_ONLY : MapMode.READ_WRITE;
|
|
||||||
final long startOfMap = chunk * chunkSize;
|
|
||||||
|
|
||||||
final long beginNs = System.nanoTime();
|
|
||||||
|
|
||||||
final long address = OS.map(fileChannel, mode, startOfMap, mappedSize);
|
|
||||||
final MappedBytesStore mbs2 = mappedBytesStoreFactory.create(owner, this, chunk * this.chunkSize, address, mappedSize, this.chunkSize);
|
|
||||||
if (RETAIN)
|
|
||||||
mbs2.reserve(this);
|
|
||||||
stores.set(chunk, mbs2);
|
|
||||||
|
|
||||||
final long elapsedNs = System.nanoTime() - beginNs;
|
|
||||||
if (newChunkListener != null)
|
|
||||||
newChunkListener.onNewChunk(file.getPath(), chunk, elapsedNs / 1000);
|
|
||||||
|
|
||||||
if (elapsedNs >= 2_000_000L)
|
|
||||||
Jvm.perf().on(getClass(), "Took " + elapsedNs / 1_000_000L + " ms to add mapping for " + file());
|
|
||||||
|
|
||||||
return mbs2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resizeRafIfTooSmall(final int chunk) throws IOException {
|
|
||||||
Jvm.safepoint();
|
|
||||||
|
|
||||||
final long minSize = (chunk + 1L) * chunkSize + overlapSize;
|
|
||||||
long size = fileChannel.size();
|
|
||||||
Jvm.safepoint();
|
|
||||||
if (size >= minSize || readOnly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// handle a possible race condition between processes.
|
|
||||||
try {
|
|
||||||
// A single JVM cannot lock a distinct canonical file more than once.
|
|
||||||
|
|
||||||
// We might have several MappedFile objects that maps to
|
|
||||||
// the same underlying file (possibly via hard or soft links)
|
|
||||||
// so we use the canonical path as a lock key
|
|
||||||
|
|
||||||
// Ensure exclusivity for any and all MappedFile objects handling
|
|
||||||
// the same canonical file.
|
|
||||||
synchronized (canonicalPath) {
|
|
||||||
size = fileChannel.size();
|
|
||||||
if (size < minSize) {
|
|
||||||
final long beginNs = System.nanoTime();
|
|
||||||
try (FileLock ignore = fileChannel.lock()) {
|
|
||||||
size = fileChannel.size();
|
|
||||||
if (size < minSize) {
|
|
||||||
Jvm.safepoint();
|
|
||||||
raf.setLength(minSize);
|
|
||||||
Jvm.safepoint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final long elapsedNs = System.nanoTime() - beginNs;
|
|
||||||
if (elapsedNs >= 1_000_000L) {
|
|
||||||
Jvm.perf().on(getClass(), "Took " + elapsedNs / 1000L + " us to grow file " + file());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new IOException("Failed to resize to " + minSize, ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method so you don't need to release the BytesStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Bytes acquireBytesForRead(ReferenceOwner owner, final long position)
|
|
||||||
throws IOException, IllegalStateException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
final MappedBytesStore mbs = acquireByteStore(owner, position, null);
|
|
||||||
final Bytes bytes = mbs.bytesForRead();
|
|
||||||
bytes.readPositionUnlimited(position);
|
|
||||||
bytes.reserveTransfer(INIT, owner);
|
|
||||||
mbs.release(owner);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void acquireBytesForRead(ReferenceOwner owner, final long position, final VanillaBytes bytes)
|
|
||||||
throws IOException, IllegalStateException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
final MappedBytesStore mbs = acquireByteStore(owner, position, null);
|
|
||||||
bytes.bytesStore(mbs, position, mbs.capacity() - position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Bytes acquireBytesForWrite(ReferenceOwner owner, final long position)
|
|
||||||
throws IOException, IllegalStateException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
MappedBytesStore mbs = acquireByteStore(owner, position, null);
|
|
||||||
Bytes bytes = mbs.bytesForWrite();
|
|
||||||
bytes.writePosition(position);
|
|
||||||
bytes.reserveTransfer(INIT, owner);
|
|
||||||
mbs.release(owner);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void acquireBytesForWrite(ReferenceOwner owner, final long position, final VanillaBytes bytes)
|
|
||||||
throws IOException, IllegalStateException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
final MappedBytesStore mbs = acquireByteStore(owner, position, null);
|
|
||||||
bytes.bytesStore(mbs, position, mbs.capacity() - position);
|
|
||||||
bytes.writePosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean performReleaseInBackground() {
|
|
||||||
// don't perform the close in the background as that just sets a flag. This does the real work.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void performRelease() {
|
|
||||||
try {
|
|
||||||
synchronized (stores) {
|
|
||||||
for (int i = 0; i < stores.size(); i++) {
|
|
||||||
final MappedBytesStore mbs = stores.get(i);
|
|
||||||
if (mbs != null && RETAIN) {
|
|
||||||
// this MappedFile is the only referrer to the MappedBytesStore at this point,
|
|
||||||
// so ensure that it is released
|
|
||||||
mbs.release(this);
|
|
||||||
}
|
|
||||||
// Dereference released entities
|
|
||||||
stores.set(i, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
closeQuietly(raf);
|
|
||||||
setClosed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String referenceCounts() {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("refCount: ").append(refCount());
|
|
||||||
for ( final MappedBytesStore mbs : stores) {
|
|
||||||
long count = 0;
|
|
||||||
if (mbs != null)
|
|
||||||
count = mbs.refCount();
|
|
||||||
sb.append(", ").append(count);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long chunkSize() {
|
|
||||||
return chunkSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long overlapSize() {
|
|
||||||
return overlapSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NewChunkListener getNewChunkListener() {
|
|
||||||
return newChunkListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNewChunkListener(final NewChunkListener listener) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
this.newChunkListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long actualSize() throws IORuntimeException {
|
|
||||||
|
|
||||||
boolean interrupted = Thread.interrupted();
|
|
||||||
try {
|
|
||||||
return fileChannel.size();
|
|
||||||
|
|
||||||
// this was seen once deep in the JVM.
|
|
||||||
} catch (ArrayIndexOutOfBoundsException aiooe) {
|
|
||||||
// try again.
|
|
||||||
return actualSize();
|
|
||||||
|
|
||||||
} catch (ClosedByInterruptException cbie) {
|
|
||||||
close();
|
|
||||||
interrupted = true;
|
|
||||||
throw new IllegalStateException(cbie);
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
final boolean open = fileChannel.isOpen();
|
|
||||||
if (open) {
|
|
||||||
throw new IORuntimeException(e);
|
|
||||||
} else {
|
|
||||||
close();
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (interrupted)
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public RandomAccessFile raf() {
|
|
||||||
return raf;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
warnAndReleaseIfNotReleased();
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean threadSafetyCheck(boolean isUsed) {
|
|
||||||
// component is thread safe
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.IOTools;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import net.openhft.chronicle.core.time.SystemTimeProvider;
|
|
||||||
import net.openhft.chronicle.core.time.TimeProvider;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamps are unique across threads/processes on a single machine.
|
|
||||||
*
|
|
||||||
* @deprecated Use {@link MappedUniqueTimeProvider} instead.
|
|
||||||
*/
|
|
||||||
@Deprecated(/* to be removed in x.23 */)
|
|
||||||
public enum MappedUniqueMicroTimeProvider implements TimeProvider {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
private static final int LAST_TIME = 128;
|
|
||||||
|
|
||||||
private final MappedFile file;
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final Bytes bytes;
|
|
||||||
private TimeProvider provider = SystemTimeProvider.INSTANCE;
|
|
||||||
|
|
||||||
MappedUniqueMicroTimeProvider() {
|
|
||||||
try {
|
|
||||||
String user = System.getProperty("user.name", "unknown");
|
|
||||||
file = MappedFile.mappedFile(OS.TMP + "/.time-stamp." + user + ".dat", OS.pageSize(), 0);
|
|
||||||
IOTools.unmonitor(file);
|
|
||||||
ReferenceOwner mumtp = ReferenceOwner.temporary("mumtp");
|
|
||||||
bytes = file.acquireBytesForWrite(mumtp, 0);
|
|
||||||
bytes.append8bit("&TSF\nTime stamp file uses for sharing a unique id\n");
|
|
||||||
IOTools.unmonitor(bytes);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new IORuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappedUniqueMicroTimeProvider provider(TimeProvider provider) {
|
|
||||||
this.provider = provider;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeMillis() {
|
|
||||||
return provider.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeMicros() {
|
|
||||||
long timeus = provider.currentTimeMicros();
|
|
||||||
while (true) {
|
|
||||||
long time0 = bytes.readVolatileLong(LAST_TIME);
|
|
||||||
long time0us = time0 / 1000;
|
|
||||||
long time;
|
|
||||||
if (time0us >= timeus)
|
|
||||||
time = (time0us + 1) * 1000;
|
|
||||||
else
|
|
||||||
time = timeus * 1000;
|
|
||||||
if (bytes.compareAndSwapLong(LAST_TIME, time0, time))
|
|
||||||
return time / 1_000;
|
|
||||||
Jvm.nanoPause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeNanos() {
|
|
||||||
long time = provider.currentTimeNanos();
|
|
||||||
while (true) {
|
|
||||||
long time0 = bytes.readVolatileLong(LAST_TIME);
|
|
||||||
if (time0 >= time)
|
|
||||||
time = time0 + 1;
|
|
||||||
if (bytes.compareAndSwapLong(LAST_TIME, time0, time))
|
|
||||||
return time;
|
|
||||||
Jvm.nanoPause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.io.IOTools;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import net.openhft.chronicle.core.time.SystemTimeProvider;
|
|
||||||
import net.openhft.chronicle.core.time.TimeProvider;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamps are unique across threads/processes on a single machine.
|
|
||||||
*/
|
|
||||||
public enum MappedUniqueTimeProvider implements TimeProvider {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
private static final int LAST_TIME = 128;
|
|
||||||
|
|
||||||
private final MappedFile file;
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final Bytes bytes;
|
|
||||||
private TimeProvider provider = SystemTimeProvider.INSTANCE;
|
|
||||||
|
|
||||||
MappedUniqueTimeProvider() {
|
|
||||||
try {
|
|
||||||
String user = System.getProperty("user.name", "unknown");
|
|
||||||
file = MappedFile.mappedFile(OS.TMP + "/.time-stamp." + user + ".dat", OS.pageSize(), 0);
|
|
||||||
IOTools.unmonitor(file);
|
|
||||||
ReferenceOwner mumtp = ReferenceOwner.temporary("mumtp");
|
|
||||||
bytes = file.acquireBytesForWrite(mumtp, 0);
|
|
||||||
bytes.append8bit("&TSF\nTime stamp file uses for sharing a unique id\n");
|
|
||||||
IOTools.unmonitor(bytes);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
throw new IORuntimeException(ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MappedUniqueTimeProvider provider(TimeProvider provider) {
|
|
||||||
this.provider = provider;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeMillis() {
|
|
||||||
return provider.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeMicros() {
|
|
||||||
long timeus = provider.currentTimeMicros();
|
|
||||||
while (true) {
|
|
||||||
long time0 = bytes.readVolatileLong(LAST_TIME);
|
|
||||||
long time0us = time0 / 1000;
|
|
||||||
long time;
|
|
||||||
if (time0us >= timeus)
|
|
||||||
time = (time0us + 1) * 1000;
|
|
||||||
else
|
|
||||||
time = timeus * 1000;
|
|
||||||
if (bytes.compareAndSwapLong(LAST_TIME, time0, time))
|
|
||||||
return time / 1_000;
|
|
||||||
Jvm.nanoPause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeNanos() {
|
|
||||||
long time = provider.currentTimeNanos();
|
|
||||||
long time5 = time >>> 5;
|
|
||||||
|
|
||||||
long time0 = bytes.readVolatileLong(LAST_TIME);
|
|
||||||
long timeNanos5 = time0 >>> 5;
|
|
||||||
|
|
||||||
if (time5 > timeNanos5)
|
|
||||||
if (bytes.compareAndSwapLong(LAST_TIME, time0, time))
|
|
||||||
return time;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
time0 = bytes.readVolatileLong(LAST_TIME);
|
|
||||||
long next = (time0 + 0x20) & ~0x1f;
|
|
||||||
if (bytes.compareAndSwapLong(LAST_TIME, time0, next))
|
|
||||||
return next;
|
|
||||||
Jvm.nanoPause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
public interface MethodEncoder {
|
|
||||||
long messageId();
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
void encode(Object[] objects, BytesOut out);
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
Object[] decode(Object[] lastObjects, BytesIn in);
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.util.Annotations;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public enum MethodEncoderLookup implements Function<Method, MethodEncoder> {
|
|
||||||
BY_ANNOTATION;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodEncoder apply(Method method) {
|
|
||||||
MethodId methodId = Annotations.getAnnotation(method, MethodId.class);
|
|
||||||
if (methodId == null) return null;
|
|
||||||
long messageId = methodId.value();
|
|
||||||
return new MethodEncoder() {
|
|
||||||
@Override
|
|
||||||
public long messageId() {
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public void encode(Object[] objects, BytesOut out) {
|
|
||||||
for (Object object : objects) {
|
|
||||||
if (object instanceof BytesMarshallable) {
|
|
||||||
((BytesMarshallable) object).writeMarshallable(out);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Object type " + object + " not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public Object[] decode(Object[] lastObjects, BytesIn in) {
|
|
||||||
for (Object lastObject : lastObjects)
|
|
||||||
((BytesMarshallable) lastObject).readMarshallable(in);
|
|
||||||
return lastObjects;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Inherited
|
|
||||||
public @interface MethodId {
|
|
||||||
long value();
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
import net.openhft.chronicle.core.util.InvocationTargetRuntimeException;
|
|
||||||
|
|
||||||
public interface MethodReader extends Closeable {
|
|
||||||
String HISTORY = "history";
|
|
||||||
|
|
||||||
MethodReaderInterceptorReturns methodReaderInterceptorReturns();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the queue to read a message if there is one, but is more expensive than {@link #lazyReadOne()}.
|
|
||||||
* If there is an exception in the dispatching mechanics then this should be caught and Jvm.warn'd.
|
|
||||||
* If there is an exception in the invocation then this is wrapped in a {@link InvocationTargetRuntimeException}
|
|
||||||
* and thrown.
|
|
||||||
*
|
|
||||||
* @return true if there was a message, false if no more messages.
|
|
||||||
* @throws InvocationTargetRuntimeException if the receiver (target method) throws
|
|
||||||
*/
|
|
||||||
boolean readOne() throws InvocationTargetRuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does a quick read which is simpler but might not read the next message. readOne() has to be called periodically.
|
|
||||||
* See also javadoc for {@link #readOne()}
|
|
||||||
*
|
|
||||||
* @return true if there was a message, false if there is probably not a message.
|
|
||||||
*/
|
|
||||||
default boolean lazyReadOne() {
|
|
||||||
return readOne();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call close on the input when closed
|
|
||||||
*/
|
|
||||||
MethodReader closeIn(boolean closeIn);
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
public interface MethodReaderBuilder {
|
|
||||||
default MethodReaderBuilder methodReaderInterceptor(MethodReaderInterceptor methodReaderInterceptor) {
|
|
||||||
return methodReaderInterceptorReturns((m, o, a, i) -> {
|
|
||||||
methodReaderInterceptor.intercept(m, o, a, i);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodReaderBuilder methodReaderInterceptorReturns(MethodReaderInterceptorReturns methodReaderInterceptorReturns);
|
|
||||||
|
|
||||||
MethodReaderBuilder warnMissing(boolean warnMissing);
|
|
||||||
|
|
||||||
MethodReader build(Object... components);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use {@link MethodReaderInterceptorReturns}
|
|
||||||
*/
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MethodReaderInterceptor {
|
|
||||||
void intercept(Method m, Object o, Object[] args, Invocation invocation) throws InvocationTargetException;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MethodReaderInterceptorReturns {
|
|
||||||
Object intercept(Method m, Object o, Object[] args, Invocation invocation) throws InvocationTargetException;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public interface MethodWriterBuilder<T> extends Supplier<T> {
|
|
||||||
|
|
||||||
MethodWriterBuilder<T> genericEvent(String genericEvent);
|
|
||||||
|
|
||||||
default MethodWriterBuilder<T> metaData(boolean metaData) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.23 */)
|
|
||||||
MethodWriterBuilder<T> useMethodIds(boolean useMethodIds);
|
|
||||||
|
|
||||||
MethodWriterBuilder<T> onClose(Closeable closeable);
|
|
||||||
|
|
||||||
// sourceId enables this, this isn't useful unless it's set.
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
MethodWriterBuilder<T> recordHistory(boolean recordHistory);
|
|
||||||
|
|
||||||
default MethodWriterBuilder<T> updateInterceptor(UpdateInterceptor updateInterceptor) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
default T build() {
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked around method writing allowing you to take action before or after method invocation,
|
|
||||||
* or even not to call the method
|
|
||||||
*
|
|
||||||
* @deprecated Use MethodWriterInterceptorReturns
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
public interface MethodWriterInterceptor {
|
|
||||||
|
|
||||||
static MethodWriterInterceptor of( final MethodWriterListener methodWriterListener, final MethodWriterInterceptor interceptor) {
|
|
||||||
if (methodWriterListener == null && interceptor == null)
|
|
||||||
throw new IllegalArgumentException("both methodWriterListener and interceptor are NULL");
|
|
||||||
|
|
||||||
if (methodWriterListener == null)
|
|
||||||
return interceptor::intercept;
|
|
||||||
|
|
||||||
if (interceptor == null)
|
|
||||||
return (method, args, invoker) -> {
|
|
||||||
methodWriterListener.onWrite(method.getName(), args);
|
|
||||||
invoker.accept(method, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (method, args, invoker) -> {
|
|
||||||
interceptor.intercept(method, args, invoker);
|
|
||||||
methodWriterListener.onWrite(method.getName(), args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void intercept(Method method, Object[] args, BiConsumer<Method, Object[]> invoker);
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Peter Lawrey so interceptors can return an object to use for chaining.
|
|
||||||
* <p>
|
|
||||||
* Invoked around method writing allowing you to take action before or after method invocation,
|
|
||||||
* or even not to call the method
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MethodWriterInterceptorReturns {
|
|
||||||
static MethodWriterInterceptorReturns of(MethodWriterInterceptor interceptor) {
|
|
||||||
return (m, a, i) -> {
|
|
||||||
interceptor.intercept(m, a, i::apply);
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static MethodWriterInterceptorReturns of( final MethodWriterListener methodWriterListener, final MethodWriterInterceptorReturns interceptor) {
|
|
||||||
if (methodWriterListener == null && interceptor == null)
|
|
||||||
throw new IllegalArgumentException("both methodWriterListener and interceptor are NULL");
|
|
||||||
|
|
||||||
if (methodWriterListener == null)
|
|
||||||
return interceptor;
|
|
||||||
|
|
||||||
if (interceptor == null)
|
|
||||||
return (method, args, invoker) -> {
|
|
||||||
methodWriterListener.onWrite(method.getName(), args);
|
|
||||||
return invoker.apply(method, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (method, args, invoker) -> {
|
|
||||||
methodWriterListener.onWrite(method.getName(), args);
|
|
||||||
return interceptor.intercept(method, args, invoker);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Object intercept(Method method, Object[] args, BiFunction<Method, Object[], Object> invoker);
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
|
|
||||||
public interface MethodWriterInvocationHandler extends InvocationHandler {
|
|
||||||
void recordHistory(boolean recordHistory);
|
|
||||||
|
|
||||||
void onClose(Closeable closeable);
|
|
||||||
|
|
||||||
default void methodWriterInterceptorReturns(MethodWriterListener methodWriterListener, MethodWriterInterceptorReturns interceptor) {
|
|
||||||
if (methodWriterListener != null || interceptor != null)
|
|
||||||
methodWriterInterceptorReturns(MethodWriterInterceptorReturns.of(methodWriterListener, interceptor));
|
|
||||||
}
|
|
||||||
|
|
||||||
void methodWriterInterceptorReturns(MethodWriterInterceptorReturns methodWriterInterceptor);
|
|
||||||
|
|
||||||
void genericEvent(String genericEvent);
|
|
||||||
|
|
||||||
void useMethodIds(boolean useMethodIds);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked before writing out this method and args.
|
|
||||||
*
|
|
||||||
* @deprecated Use MethodWriterInterceptorReturns
|
|
||||||
*/
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface MethodWriterListener {
|
|
||||||
void onWrite(String name, Object[] args);
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface MultiReaderBytesRingBuffer extends BytesRingBuffer {
|
|
||||||
|
|
||||||
|
|
||||||
default RingBufferReader createReader() {
|
|
||||||
return createReader(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a reader
|
|
||||||
*
|
|
||||||
* @param id of reader as each reader has separate read position etc.
|
|
||||||
* @return reader
|
|
||||||
*/
|
|
||||||
|
|
||||||
RingBufferReader createReader(int id);
|
|
||||||
}
|
|
|
@ -1,409 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.util.DecoratedBufferOverflowException;
|
|
||||||
import net.openhft.chronicle.core.*;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.NativeBytesStore.nativeStoreWithFixedCapacity;
|
|
||||||
import static net.openhft.chronicle.bytes.NoBytesStore.noBytesStore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Elastic memory accessor which can wrap either a ByteBuffer or malloc'ed memory.
|
|
||||||
* <p>
|
|
||||||
* <p>This class can wrap <i>heap</i> ByteBuffers, called <i>Native</i>Bytes for historical reasons.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class NativeBytes<Underlying>
|
|
||||||
extends VanillaBytes<Underlying> {
|
|
||||||
private static final boolean BYTES_GUARDED = Jvm.getBoolean("bytes.guarded");
|
|
||||||
private static boolean s_newGuarded = BYTES_GUARDED;
|
|
||||||
private final long capacity;
|
|
||||||
|
|
||||||
public NativeBytes( final BytesStore store, final long capacity) throws IllegalStateException {
|
|
||||||
super(store, 0, capacity);
|
|
||||||
this.capacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeBytes( final BytesStore store) throws IllegalStateException {
|
|
||||||
super(store, 0, store.capacity());
|
|
||||||
capacity = store.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*
|
|
||||||
* @return will new NativeBytes be guarded.
|
|
||||||
*/
|
|
||||||
public static boolean areNewGuarded() {
|
|
||||||
return s_newGuarded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* turn guarding on/off. Can be enabled by assertion with
|
|
||||||
* <code>
|
|
||||||
* assert NativeBytes.setNewGuarded(true);
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @param guarded turn on if true
|
|
||||||
*/
|
|
||||||
public static boolean setNewGuarded(final boolean guarded) {
|
|
||||||
s_newGuarded = guarded;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For testing
|
|
||||||
*/
|
|
||||||
public static void resetNewGuarded() {
|
|
||||||
s_newGuarded = BYTES_GUARDED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytes<Void> nativeBytes() {
|
|
||||||
try {
|
|
||||||
return NativeBytes.wrapWithNativeBytes(noBytesStore(), Bytes.MAX_CAPACITY);
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytes<Void> nativeBytes(final long initialCapacity) throws IllegalArgumentException {
|
|
||||||
final NativeBytesStore<Void> store = nativeStoreWithFixedCapacity(initialCapacity);
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
return NativeBytes.wrapWithNativeBytes(store, Bytes.MAX_CAPACITY);
|
|
||||||
} finally {
|
|
||||||
store.release(INIT);
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BytesStore<Bytes<Void>, Void> copyOf( final Bytes bytes) {
|
|
||||||
final long remaining = bytes.readRemaining();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final NativeBytes<Void> bytes2 = Bytes.allocateElasticDirect(remaining);
|
|
||||||
bytes2.write(bytes, 0, remaining);
|
|
||||||
return bytes2;
|
|
||||||
} catch (IllegalArgumentException | BufferOverflowException | BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long alignToPageSize(final long size) {
|
|
||||||
long mask = OS.pageSize() - 1;
|
|
||||||
return (size + mask) & ~mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static <T> NativeBytes<T> wrapWithNativeBytes( final BytesStore<?, T> bs, long capacity) {
|
|
||||||
return s_newGuarded
|
|
||||||
? new GuardedNativeBytes(bs, capacity)
|
|
||||||
: new NativeBytes<>(bs, capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static <T> long maxCapacityFor( BytesStore<?, T> bs) {
|
|
||||||
return bs.underlyingObject() instanceof ByteBuffer
|
|
||||||
|| bs.underlyingObject() instanceof byte[]
|
|
||||||
? MAX_HEAP_CAPACITY
|
|
||||||
: Bytes.MAX_CAPACITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeCheckOffset(final long offset, final long adding) throws BufferOverflowException {
|
|
||||||
if (offset >= bytesStore.start()) {
|
|
||||||
final long writeEnd = offset + adding;
|
|
||||||
if (writeEnd <= bytesStore.safeLimit()) {
|
|
||||||
return; // do nothing.
|
|
||||||
}
|
|
||||||
if (writeEnd >= capacity)
|
|
||||||
throw new BufferOverflowException(/*"Write exceeds capacity"*/);
|
|
||||||
checkResize(writeEnd);
|
|
||||||
} else {
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void prewriteCheckOffset(long offset, long subtracting) throws BufferOverflowException {
|
|
||||||
if (offset - subtracting >= bytesStore.start()) {
|
|
||||||
if (offset <= bytesStore.safeLimit()) {
|
|
||||||
return; // do nothing.
|
|
||||||
}
|
|
||||||
if (offset >= capacity)
|
|
||||||
throw new BufferOverflowException(/*"Write exceeds capacity"*/);
|
|
||||||
checkResize(offset);
|
|
||||||
} else {
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ensureCapacity(final long size) throws IllegalArgumentException {
|
|
||||||
try {
|
|
||||||
assert size >= 0;
|
|
||||||
writeCheckOffset(writePosition(), size);
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
IllegalArgumentException iae = new IllegalArgumentException("Bytes cannot be resized to " + size + " limit: " + capacity());
|
|
||||||
iae.printStackTrace();
|
|
||||||
throw iae;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkResize(final long endOfBuffer) throws BufferOverflowException {
|
|
||||||
if (isElastic())
|
|
||||||
resize(endOfBuffer);
|
|
||||||
else
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isElastic() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the endOfBuffer is the minimum capacity and one byte more than the last addressable byte.
|
|
||||||
private void resize(final long endOfBuffer)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
throwExceptionIfReleased();
|
|
||||||
if (endOfBuffer < 0)
|
|
||||||
throw new DecoratedBufferOverflowException(endOfBuffer + "< 0");
|
|
||||||
if (endOfBuffer > capacity())
|
|
||||||
throw new DecoratedBufferOverflowException(endOfBuffer + ">" + capacity());
|
|
||||||
final long realCapacity = realCapacity();
|
|
||||||
if (endOfBuffer <= realCapacity) {
|
|
||||||
// System.out.println("no resize " + endOfBuffer + " < " + realCapacity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grow by 50%
|
|
||||||
long size = Math.max(endOfBuffer + 7, realCapacity * 3 / 2 + 32);
|
|
||||||
if (isDirectMemory() || size > MAX_HEAP_CAPACITY) {
|
|
||||||
// Allocate direct memory of page granularity
|
|
||||||
size = alignToPageSize(size);
|
|
||||||
} else {
|
|
||||||
size &= ~0x7;
|
|
||||||
}
|
|
||||||
// Cap the size with capacity() again
|
|
||||||
size = Math.min(size, capacity());
|
|
||||||
|
|
||||||
final boolean isByteBufferBacked = bytesStore.underlyingObject() instanceof ByteBuffer;
|
|
||||||
if (isByteBufferBacked && size > MAX_HEAP_CAPACITY) {
|
|
||||||
|
|
||||||
// Add a stack trace to this relatively unusual event which will
|
|
||||||
// enable tracing of potentially derailed code or excessive buffer use.
|
|
||||||
final StackTrace stackTrace = new StackTrace();
|
|
||||||
final String stack = BytesUtil.asString("Calling stack is", stackTrace);
|
|
||||||
|
|
||||||
Jvm.warn().on(getClass(), "Going to try to replace ByteBuffer-backed BytesStore with " +
|
|
||||||
"raw NativeBytesStore to grow to " + size / 1024 + " KB. If later it is assumed that " +
|
|
||||||
"this bytes' underlyingObject() is ByteBuffer, NullPointerException is likely to be thrown. " +
|
|
||||||
stack);
|
|
||||||
}
|
|
||||||
// System.out.println("resize " + endOfBuffer + " to " + size);
|
|
||||||
if (endOfBuffer > 1 << 20)
|
|
||||||
Jvm.warn().on(getClass(), "Resizing buffer was " + realCapacity / 1024 + " KB, " +
|
|
||||||
"needs " + (endOfBuffer - realCapacity) + " bytes more, " +
|
|
||||||
"new-size " + size / 1024 + " KB");
|
|
||||||
final BytesStore store;
|
|
||||||
int position = 0;
|
|
||||||
try {
|
|
||||||
if (isByteBufferBacked && size <= MAX_HEAP_CAPACITY) {
|
|
||||||
position = ((ByteBuffer) bytesStore.underlyingObject()).position();
|
|
||||||
store = allocateNewByteBufferBackedStore(Maths.toInt32(size));
|
|
||||||
} else {
|
|
||||||
store = NativeBytesStore.lazyNativeBytesStoreWithFixedCapacity(size);
|
|
||||||
}
|
|
||||||
store.reserveTransfer(INIT, this);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
BufferOverflowException boe = new BufferOverflowException();
|
|
||||||
boe.initCause(e);
|
|
||||||
throw boe;
|
|
||||||
}
|
|
||||||
|
|
||||||
throwExceptionIfReleased();
|
|
||||||
final BytesStore<Bytes<Underlying>, Underlying> tempStore = this.bytesStore;
|
|
||||||
this.bytesStore.copyTo(store);
|
|
||||||
this.bytesStore(store);
|
|
||||||
try {
|
|
||||||
tempStore.release(this);
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Jvm.debug().on(getClass(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.bytesStore.underlyingObject() instanceof ByteBuffer) {
|
|
||||||
final ByteBuffer byteBuffer = (ByteBuffer) this.bytesStore.underlyingObject();
|
|
||||||
byteBuffer.position(0);
|
|
||||||
byteBuffer.limit(byteBuffer.capacity());
|
|
||||||
byteBuffer.position(position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private BytesStore allocateNewByteBufferBackedStore(final int size) {
|
|
||||||
if (isDirectMemory()) {
|
|
||||||
return NativeBytesStore.elasticByteBuffer(size, capacity());
|
|
||||||
} else {
|
|
||||||
return HeapBytesStore.wrap(ByteBuffer.allocate(size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( final byte[] bytes,
|
|
||||||
final int offset,
|
|
||||||
final int length) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
if (length > writeRemaining())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
ensureCapacity(length);
|
|
||||||
super.write(bytes, offset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Bytes<Underlying> write( final BytesStore bytes,
|
|
||||||
final long offset,
|
|
||||||
final long length) throws BufferOverflowException, IllegalArgumentException, BufferUnderflowException {
|
|
||||||
ensureCapacity(length);
|
|
||||||
super.write(bytes, offset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public NativeBytes writeSome( final Bytes bytes) {
|
|
||||||
try {
|
|
||||||
long length = Math.min(bytes.readRemaining(), writeRemaining());
|
|
||||||
if (length + writePosition() >= 1 << 20)
|
|
||||||
length = Math.min(bytes.readRemaining(), realCapacity() - writePosition());
|
|
||||||
final long offset = bytes.readPosition();
|
|
||||||
ensureCapacity(length);
|
|
||||||
optimisedWrite(bytes, offset, length);
|
|
||||||
if (length == bytes.readRemaining()) {
|
|
||||||
bytes.clear();
|
|
||||||
} else {
|
|
||||||
bytes.readSkip(length);
|
|
||||||
if (bytes.writePosition() > bytes.realCapacity() / 2)
|
|
||||||
bytes.compact();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
} catch (IllegalArgumentException | BufferUnderflowException | BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long writeOffsetPositionMoved(final long adding, final long advance) throws BufferOverflowException {
|
|
||||||
final long oldPosition = writePosition;
|
|
||||||
if (writePosition < bytesStore.start())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
final long writeEnd = writePosition + adding;
|
|
||||||
if (writeEnd > writeLimit)
|
|
||||||
throwBeyondWriteLimit(advance, writeEnd);
|
|
||||||
else if (writeEnd > bytesStore.safeLimit())
|
|
||||||
checkResize(writeEnd);
|
|
||||||
this.writePosition = writePosition + advance;
|
|
||||||
return oldPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void throwBeyondWriteLimit(long advance, long writeEnd) {
|
|
||||||
throw new DecoratedBufferOverflowException("attempt to write " + advance + " bytes to " + writeEnd + " limit: " + writeLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeByte(final byte i8) throws BufferOverflowException {
|
|
||||||
final long offset = writeOffsetPositionMoved(1, 1);
|
|
||||||
bytesStore.writeByte(offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write8bit( final BytesStore bs) throws BufferOverflowException {
|
|
||||||
if (bs == null) {
|
|
||||||
writeStopBit(-1);
|
|
||||||
} else {
|
|
||||||
final long offset = bs.readPosition();
|
|
||||||
final long readRemaining = Math.min(writeRemaining(), bs.readLimit() - offset);
|
|
||||||
writeStopBit(readRemaining);
|
|
||||||
write(bs, offset, readRemaining);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeLong(final long i64) throws BufferOverflowException {
|
|
||||||
final long offset = writeOffsetPositionMoved(8L, 8L);
|
|
||||||
bytesStore.writeLong(offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readRemaining() {
|
|
||||||
return writePosition - readPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static class NativeSubBytes extends SubBytes {
|
|
||||||
private final NativeBytesStore nativeBytesStore;
|
|
||||||
|
|
||||||
public NativeSubBytes( final BytesStore bytesStore,
|
|
||||||
final long start,
|
|
||||||
final long capacity) throws IllegalStateException {
|
|
||||||
super(bytesStore, start, capacity);
|
|
||||||
nativeBytesStore = (NativeBytesStore) this.bytesStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long read(final long offsetInRDI,
|
|
||||||
final byte[] bytes,
|
|
||||||
final int offset,
|
|
||||||
final int length) {
|
|
||||||
|
|
||||||
final int len = (int) Math.min(length, readLimit() - offsetInRDI);
|
|
||||||
int i;
|
|
||||||
final long address = nativeBytesStore.address + nativeBytesStore.translate(offsetInRDI);
|
|
||||||
for (i = 0; i < len - 7; i += 8)
|
|
||||||
UnsafeMemory.unsafePutLong(bytes, i, nativeBytesStore.memory.readLong(address + i));
|
|
||||||
if (i < len - 3) {
|
|
||||||
UnsafeMemory.unsafePutInt(bytes, i, nativeBytesStore.memory.readInt(address + i));
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
for (; i < len; i++)
|
|
||||||
UnsafeMemory.unsafePutByte(bytes, i, nativeBytesStore.memory.readByte(address + i));
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,852 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.*;
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.cleaner.CleanerServiceLocator;
|
|
||||||
import net.openhft.chronicle.core.cleaner.spi.ByteBufferCleanerService;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.util.SimpleCleaner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.Bytes.MAX_CAPACITY;
|
|
||||||
|
|
||||||
@SuppressWarnings({"restriction", "rawtypes", "unchecked"})
|
|
||||||
public class NativeBytesStore<Underlying>
|
|
||||||
extends AbstractBytesStore<NativeBytesStore<Underlying>, Underlying> {
|
|
||||||
private static final long MEMORY_MAPPED_SIZE = 128 << 10;
|
|
||||||
private static final Field BB_ADDRESS, BB_CAPACITY, BB_ATT;
|
|
||||||
private static final ByteBufferCleanerService CLEANER_SERVICE = CleanerServiceLocator.cleanerService();
|
|
||||||
// static MappedBytes last;
|
|
||||||
|
|
||||||
static {
|
|
||||||
Class directBB = ByteBuffer.allocateDirect(0).getClass();
|
|
||||||
BB_ADDRESS = Jvm.getField(directBB, "address");
|
|
||||||
BB_CAPACITY = Jvm.getField(directBB, "capacity");
|
|
||||||
BB_ATT = Jvm.getField(directBB, "att");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long address;
|
|
||||||
// on release, set this to null.
|
|
||||||
protected Memory memory = OS.memory();
|
|
||||||
protected long limit, maximumLimit;
|
|
||||||
|
|
||||||
private SimpleCleaner cleaner;
|
|
||||||
private boolean elastic;
|
|
||||||
|
|
||||||
private Underlying underlyingObject;
|
|
||||||
private final Finalizer finalizer;
|
|
||||||
|
|
||||||
private NativeBytesStore() {
|
|
||||||
finalizer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NativeBytesStore( ByteBuffer bb, boolean elastic) {
|
|
||||||
this(bb, elastic, Bytes.MAX_HEAP_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeBytesStore( ByteBuffer bb, boolean elastic, int maximumLimit) {
|
|
||||||
this();
|
|
||||||
init(bb, elastic);
|
|
||||||
this.maximumLimit = elastic ? maximumLimit : Math.min(limit, maximumLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeBytesStore(
|
|
||||||
long address, long limit) {
|
|
||||||
this(address, limit, null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeBytesStore(
|
|
||||||
long address, long limit, Runnable deallocator, boolean elastic) {
|
|
||||||
this(address, limit, deallocator, elastic, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NativeBytesStore(
|
|
||||||
long address, long limit, Runnable deallocator, boolean elastic, boolean monitored) {
|
|
||||||
super(monitored);
|
|
||||||
setAddress(address);
|
|
||||||
this.limit = limit;
|
|
||||||
this.maximumLimit = elastic ? MAX_CAPACITY : limit;
|
|
||||||
this.cleaner = deallocator == null ? null : new SimpleCleaner(deallocator);
|
|
||||||
underlyingObject = null;
|
|
||||||
this.elastic = elastic;
|
|
||||||
if (cleaner == null)
|
|
||||||
finalizer = null;
|
|
||||||
else
|
|
||||||
finalizer = new Finalizer();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore<ByteBuffer> wrap( ByteBuffer bb) {
|
|
||||||
return new NativeBytesStore<>(bb, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static <T> NativeBytesStore<T> uninitialized() {
|
|
||||||
return new NativeBytesStore<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* this is an elastic native store
|
|
||||||
*
|
|
||||||
* @param capacity of the buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static NativeBytesStore<Void> nativeStore(long capacity)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
return of(capacity, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static NativeBytesStore<Void> of(long capacity, boolean zeroOut, boolean elastic)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
if (capacity <= 0)
|
|
||||||
return new NativeBytesStore<>(NoBytesStore.NO_PAGE, 0, null, elastic);
|
|
||||||
Memory memory = OS.memory();
|
|
||||||
long address = memory.allocate(capacity);
|
|
||||||
if (zeroOut || capacity < MEMORY_MAPPED_SIZE) {
|
|
||||||
memory.setMemory(address, capacity, (byte) 0);
|
|
||||||
memory.storeFence();
|
|
||||||
}
|
|
||||||
Deallocator deallocator = new Deallocator(address, capacity);
|
|
||||||
return new NativeBytesStore<>(address, capacity, deallocator, elastic);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore<Void> nativeStoreWithFixedCapacity(long capacity)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
return of(capacity, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore<Void> lazyNativeBytesStoreWithFixedCapacity(long capacity)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
return of(capacity, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore<ByteBuffer> elasticByteBuffer() {
|
|
||||||
return elasticByteBuffer(OS.pageSize(), MAX_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore<ByteBuffer> elasticByteBuffer(int size, long maxSize) {
|
|
||||||
return new NativeBytesStore<>(ByteBuffer.allocateDirect(size), true, Math.toIntExact(maxSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore from( String text) {
|
|
||||||
return from(text.getBytes(StandardCharsets.ISO_8859_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static NativeBytesStore from( byte[] bytes) {
|
|
||||||
try {
|
|
||||||
NativeBytesStore nbs = nativeStoreWithFixedCapacity(bytes.length);
|
|
||||||
Bytes<byte[]> bytes2 = Bytes.wrapForRead(bytes);
|
|
||||||
bytes2.copyTo(nbs);
|
|
||||||
bytes2.releaseLast();
|
|
||||||
return nbs;
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirectMemory() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canReadDirect(long length) {
|
|
||||||
return limit >= length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init( ByteBuffer bb, boolean elastic) {
|
|
||||||
this.elastic = elastic;
|
|
||||||
underlyingObject = (Underlying) bb;
|
|
||||||
setAddress(Jvm.address(bb));
|
|
||||||
this.limit = bb.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void uninit() {
|
|
||||||
underlyingObject = null;
|
|
||||||
address = 0;
|
|
||||||
limit = 0;
|
|
||||||
maximumLimit = 0;
|
|
||||||
cleaner = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(long from, long to, long length) throws BufferUnderflowException {
|
|
||||||
if (from < 0 || to < 0) throw new BufferUnderflowException();
|
|
||||||
long address = this.address;
|
|
||||||
if (address == 0) throwException(null);
|
|
||||||
memoryCopyMemory(address + from, address + to, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void memoryCopyMemory(long fromAddress, long toAddress, long length) {
|
|
||||||
try {
|
|
||||||
memory.copyMemory(fromAddress, toAddress, length);
|
|
||||||
} catch (NullPointerException ifReleased) {
|
|
||||||
throwException(ifReleased);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void throwException(Throwable ifReleased) {
|
|
||||||
throwExceptionIfReleased();
|
|
||||||
throw new IllegalStateException(ifReleased);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore<NativeBytesStore<Underlying>, Underlying> copy() {
|
|
||||||
try {
|
|
||||||
if (underlyingObject == null) {
|
|
||||||
NativeBytesStore<Void> copy = of(realCapacity(), false, true);
|
|
||||||
memoryCopyMemory(address, copy.address, capacity());
|
|
||||||
return (BytesStore) copy;
|
|
||||||
|
|
||||||
} else if (underlyingObject instanceof ByteBuffer) {
|
|
||||||
ByteBuffer bb = ByteBuffer.allocateDirect(Maths.toInt32(capacity()));
|
|
||||||
bb.put((ByteBuffer) underlyingObject);
|
|
||||||
bb.clear();
|
|
||||||
return (BytesStore) wrap(bb);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VanillaBytes<Underlying> bytesForWrite() throws IllegalStateException {
|
|
||||||
return elastic
|
|
||||||
? NativeBytes.wrapWithNativeBytes(this, this.capacity())
|
|
||||||
: new VanillaBytes<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long realCapacity() {
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long capacity() {
|
|
||||||
return maximumLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Underlying underlyingObject() {
|
|
||||||
return underlyingObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> zeroOut(long start, long end) {
|
|
||||||
if (end <= start)
|
|
||||||
return this;
|
|
||||||
if (start < start())
|
|
||||||
start = start();
|
|
||||||
if (end > capacity())
|
|
||||||
end = capacity();
|
|
||||||
|
|
||||||
memory.setMemory(address + translate(start), end - start, (byte) 0);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value) {
|
|
||||||
return memory.compareAndSwapInt(address + translate(offset), expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testAndSetInt(long offset, int expected, int value) {
|
|
||||||
memory.testAndSetInt(address + translate(offset), offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value) {
|
|
||||||
return memory.compareAndSwapLong(address + translate(offset), expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long addAndGetLong(long offset, long adding) throws BufferUnderflowException {
|
|
||||||
return memory.addLong(address + translate(offset), adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int addAndGetInt(long offset, int adding) throws BufferUnderflowException {
|
|
||||||
return memory.addInt(address + translate(offset), adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long translate(long offset) {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public byte readByte(long offset) {
|
|
||||||
return memory.readByte(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedByte(long offset) throws BufferUnderflowException {
|
|
||||||
return readByte(offset) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public short readShort(long offset) {
|
|
||||||
return memory.readShort(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int readInt(long offset) {
|
|
||||||
return memory.readInt(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readLong(long offset) {
|
|
||||||
long address = this.address;
|
|
||||||
assert address != 0;
|
|
||||||
return memory.readLong(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public float readFloat(long offset) {
|
|
||||||
return memory.readFloat(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public double readDouble(long offset) {
|
|
||||||
return memory.readDouble(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public byte readVolatileByte(long offset) {
|
|
||||||
return memory.readVolatileByte(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public short readVolatileShort(long offset) {
|
|
||||||
return memory.readVolatileShort(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int readVolatileInt(long offset) {
|
|
||||||
return memory.readVolatileInt(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readVolatileLong(long offset) {
|
|
||||||
return memory.readVolatileLong(address + translate(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeByte(long offset, byte i8) {
|
|
||||||
memory.writeByte(address + translate(offset), i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeShort(long offset, short i16) {
|
|
||||||
memory.writeShort(address + translate(offset), i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeInt(long offset, int i32) {
|
|
||||||
try {
|
|
||||||
memory.writeInt(address + translate(offset), i32);
|
|
||||||
return this;
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfReleased();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeOrderedInt(long offset, int i) {
|
|
||||||
memory.writeOrderedInt(address + translate(offset), i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeLong(long offset, long i64) {
|
|
||||||
memory.writeLong(address + translate(offset), i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeOrderedLong(long offset, long i) {
|
|
||||||
memory.writeOrderedLong(address + translate(offset), i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeFloat(long offset, float f) {
|
|
||||||
memory.writeFloat(address + translate(offset), f);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeDouble(long offset, double d) {
|
|
||||||
memory.writeDouble(address + translate(offset), d);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeVolatileByte(long offset, byte i8) {
|
|
||||||
memory.writeVolatileByte(address + translate(offset), i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeVolatileShort(long offset, short i16) {
|
|
||||||
memory.writeVolatileShort(address + translate(offset), i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeVolatileInt(long offset, int i32) {
|
|
||||||
memory.writeVolatileInt(address + translate(offset), i32);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> writeVolatileLong(long offset, long i64) {
|
|
||||||
memory.writeVolatileLong(address + translate(offset), i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> write(
|
|
||||||
long offsetInRDO, byte[] bytes, int offset, int length) {
|
|
||||||
memory.copyMemory(bytes, offset, address + translate(offsetInRDO), length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void write(
|
|
||||||
long offsetInRDO, ByteBuffer bytes, int offset, int length) {
|
|
||||||
if (bytes.isDirect()) {
|
|
||||||
memoryCopyMemory(Jvm.address(bytes) + offset, address + translate(offsetInRDO), length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memory.copyMemory(bytes.array(), offset, address + translate(offsetInRDO), length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public NativeBytesStore<Underlying> write(
|
|
||||||
long writeOffset, RandomDataInput bytes, long readOffset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
if (bytes.isDirectMemory()) {
|
|
||||||
memoryCopyMemory(bytes.addressForRead(readOffset), addressForWrite(writeOffset), length);
|
|
||||||
} else {
|
|
||||||
write0(writeOffset, bytes, readOffset, length);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write0(long offsetInRDO, RandomDataInput bytes, long offset, long length) throws BufferUnderflowException {
|
|
||||||
long i = 0;
|
|
||||||
for (; i < length - 7; i += 8) {
|
|
||||||
writeLong(offsetInRDO + i, bytes.readLong(offset + i));
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
writeByte(offsetInRDO + i, bytes.readByte(offset + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForRead(long offset) throws BufferUnderflowException {
|
|
||||||
if (offset < start() || offset > realCapacity())
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
return address + translate(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWrite(long offset) throws BufferOverflowException {
|
|
||||||
if (offset < start() || offset > realCapacity())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
return address + translate(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWritePosition() throws UnsupportedOperationException, BufferOverflowException {
|
|
||||||
return addressForWrite(start());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performRelease() {
|
|
||||||
memory = null;
|
|
||||||
if (cleaner != null) {
|
|
||||||
cleaner.clean();
|
|
||||||
|
|
||||||
} else if (underlyingObject instanceof ByteBuffer) {
|
|
||||||
ByteBuffer underlyingObject = (ByteBuffer) this.underlyingObject;
|
|
||||||
if (underlyingObject.isDirect())
|
|
||||||
CLEANER_SERVICE.clean(underlyingObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
try {
|
|
||||||
return BytesInternal.toString(this);
|
|
||||||
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
return e.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void nativeRead(long position, long address, long size) throws BufferUnderflowException {
|
|
||||||
// TODO add bounds checking.
|
|
||||||
memoryCopyMemory(addressForRead(position), address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void nativeWrite(long address, long position, long size) throws BufferOverflowException {
|
|
||||||
// TODO add bounds checking.
|
|
||||||
memoryCopyMemory(address, addressForWrite(position), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write8bit(long position, char[] chars, int offset, int length) {
|
|
||||||
long addr = address + translate(position);
|
|
||||||
Memory memory = this.memory;
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
memory.writeByte(addr + i, (byte) chars[offset + i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read8bit(long position, char[] chars, int length) {
|
|
||||||
long addr = address + translate(position);
|
|
||||||
Memory memory = this.memory;
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
chars[i] = (char) (memory.readByte(addr + i) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readIncompleteLong(long offset) {
|
|
||||||
int remaining = (int) Math.min(8, readRemaining() - offset);
|
|
||||||
long l = 0;
|
|
||||||
for (int i = 0; i < remaining; i++) {
|
|
||||||
byte b = memory.readByte(address + offset + i);
|
|
||||||
l |= (long) (b & 0xFF) << (i * 8);
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return obj instanceof BytesStore && BytesInternal.contentEqual(this, (BytesStore) obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddress(long address) {
|
|
||||||
if ((address & ~0x3FFF) == 0)
|
|
||||||
throw new AssertionError("Invalid addressForRead " + Long.toHexString(address));
|
|
||||||
this.address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
public long appendUTF(long pos, char[] chars, int offset, int length) throws BufferOverflowException {
|
|
||||||
return appendUtf8(pos, chars, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long appendUtf8(long pos, char[] chars, int offset, int length) throws BufferOverflowException {
|
|
||||||
if (pos + length > realCapacity())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
|
|
||||||
long address = this.address + translate(0);
|
|
||||||
Memory memory = this.memory;
|
|
||||||
if (memory == null) throw new NullPointerException();
|
|
||||||
int i;
|
|
||||||
ascii:
|
|
||||||
{
|
|
||||||
for (i = 0; i < length - 3; i += 4) {
|
|
||||||
final int i2 = offset + i;
|
|
||||||
char c0 = chars[i2];
|
|
||||||
char c1 = chars[i2 + 1];
|
|
||||||
char c2 = chars[i2 + 2];
|
|
||||||
char c3 = chars[i2 + 3];
|
|
||||||
if ((c0 | c1 | c2 | c3) > 0x007F)
|
|
||||||
break ascii;
|
|
||||||
final int value = (c0) | (c1 << 8) | (c2 << 16) | (c3 << 24);
|
|
||||||
UnsafeMemory.unsafePutInt(address + pos, value);
|
|
||||||
pos += 4;
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
if (c > 0x007F)
|
|
||||||
break ascii;
|
|
||||||
UnsafeMemory.unsafePutByte(address + pos++, (byte) c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
return appendUtf8a(pos, chars, offset, length, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long appendUtf8a(long pos, char[] chars, int offset, int length, int i) {
|
|
||||||
for (; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
if (c <= 0x007F) {
|
|
||||||
writeByte(pos++, (byte) c);
|
|
||||||
|
|
||||||
} else if (c <= 0x07FF) {
|
|
||||||
writeByte(pos++, (byte) (0xC0 | ((c >> 6) & 0x1F)));
|
|
||||||
writeByte(pos++, (byte) (0x80 | c & 0x3F));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
writeByte(pos++, (byte) (0xE0 | ((c >> 12) & 0x0F)));
|
|
||||||
writeByte(pos++, (byte) (0x80 | ((c >> 6) & 0x3F)));
|
|
||||||
writeByte(pos++, (byte) (0x80 | (c & 0x3F)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long copyTo( BytesStore store) {
|
|
||||||
if (store.isDirectMemory())
|
|
||||||
return copyToDirect(store);
|
|
||||||
else
|
|
||||||
return super.copyTo(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long copyToDirect( BytesStore store) {
|
|
||||||
long toCopy = Math.min(limit, store.safeLimit());
|
|
||||||
if (toCopy > 0) {
|
|
||||||
try {
|
|
||||||
long addr = address;
|
|
||||||
long addr2 = store.addressForWrite(0);
|
|
||||||
memoryCopyMemory(addr, addr2, toCopy);
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return toCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuffer toTemporaryDirectByteBuffer() {
|
|
||||||
ByteBuffer bb = ByteBuffer.allocateDirect(0);
|
|
||||||
try {
|
|
||||||
BB_ADDRESS.setLong(bb, address);
|
|
||||||
BB_CAPACITY.setInt(bb, Maths.toUInt31(readRemaining()));
|
|
||||||
BB_ATT.set(bb, this);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
bb.clear();
|
|
||||||
return bb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int byteCheckSum() throws IORuntimeException {
|
|
||||||
return byteCheckSum(start(), readLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public int byteCheckSum(long position, long limit) {
|
|
||||||
Memory memory = this.memory;
|
|
||||||
assert memory != null;
|
|
||||||
int b = 0;
|
|
||||||
long ptr = address + position;
|
|
||||||
long end = address + limit;
|
|
||||||
for (; ptr < end - 7; ptr += 8) {
|
|
||||||
b += memory.readByte(ptr)
|
|
||||||
+ memory.readByte(ptr + 1)
|
|
||||||
+ memory.readByte(ptr + 2)
|
|
||||||
+ memory.readByte(ptr + 3)
|
|
||||||
+ memory.readByte(ptr + 4)
|
|
||||||
+ memory.readByte(ptr + 5)
|
|
||||||
+ memory.readByte(ptr + 6)
|
|
||||||
+ memory.readByte(ptr + 7);
|
|
||||||
}
|
|
||||||
for (; ptr < end; ptr++) {
|
|
||||||
b += memory.readByte(ptr);
|
|
||||||
}
|
|
||||||
return b & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sharedMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long read(long offsetInRDI, byte[] bytes, int offset, int length) {
|
|
||||||
int len = (int) Math.min(length, readLimit() - offsetInRDI);
|
|
||||||
int i;
|
|
||||||
final long address = this.address + translate(offsetInRDI);
|
|
||||||
for (i = 0; i < len - 7; i += 8)
|
|
||||||
UnsafeMemory.unsafePutLong(bytes, i, memory.readLong(address + i));
|
|
||||||
if (i < len - 3) {
|
|
||||||
UnsafeMemory.unsafePutInt(bytes, i, memory.readInt(address + i));
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
for (; i < len; i++)
|
|
||||||
UnsafeMemory.unsafePutByte(bytes, i, memory.readByte(address + i));
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int peekUnsignedByte(long offset) {
|
|
||||||
final long address = this.address;
|
|
||||||
final Memory memory = this.memory;
|
|
||||||
final long translate = translate(offset);
|
|
||||||
// assert translate >= 0;
|
|
||||||
final long address2 = address + translate;
|
|
||||||
// last.writeLong(8, Thread.currentThread().getId());
|
|
||||||
// last.writeLong(0, offset);
|
|
||||||
// last.writeLong(16, translate);
|
|
||||||
// last.writeLong(32, maximumLimit);
|
|
||||||
// last.writeLong(48, addressForRead);
|
|
||||||
// last.writeLong(64, address2);
|
|
||||||
// last.writeBoolean(80, memory != null);
|
|
||||||
// last.writeVolatileByte(88, (byte) 1);
|
|
||||||
int ret = translate >= limit ? -1 :
|
|
||||||
memory.readByte(address2) & 0xFF;
|
|
||||||
// last.writeVolatileByte(88, (byte) 0xFF);
|
|
||||||
// last.writeLong(24, Thread.currentThread().getId());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int fastHash(long offset, int length) throws BufferUnderflowException {
|
|
||||||
long ret;
|
|
||||||
switch (length) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
ret = readByte(offset);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ret = readShort(offset);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
ret = readInt(offset);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
ret = readInt(offset) * 0x6d0f27bdL + readInt(offset + 4);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return super.fastHash(offset, length);
|
|
||||||
}
|
|
||||||
long hash = ret * 0x855dd4db;
|
|
||||||
return (int) (hash ^ (hash >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long safeLimit() {
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Deallocator implements Runnable {
|
|
||||||
|
|
||||||
private volatile long address;
|
|
||||||
private final long size;
|
|
||||||
|
|
||||||
Deallocator(long address, long size) {
|
|
||||||
assert address != 0;
|
|
||||||
this.address = address;
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// System.out.println("Release " + Long.toHexString(addressForRead));
|
|
||||||
if (address == 0)
|
|
||||||
return;
|
|
||||||
long addressToFree = address;
|
|
||||||
address = 0;
|
|
||||||
OS.memory().freeMemory(addressToFree, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Finalizer {
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
super.finalize();
|
|
||||||
warnAndReleaseIfNotReleased();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface NewChunkListener {
|
|
||||||
void onNewChunk(String filename, int chunk, long delayMicros);
|
|
||||||
}
|
|
|
@ -1,338 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.io.IOTools;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a ByteStore which uses no space but could be resized to be larger (by replacing it with a ByteStire with space)
|
|
||||||
*
|
|
||||||
* @see ReleasedBytesStore
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public enum NoBytesStore implements BytesStore {
|
|
||||||
NO_BYTES_STORE;
|
|
||||||
|
|
||||||
public static final long NO_PAGE;
|
|
||||||
|
|
||||||
|
|
||||||
public static final Bytes NO_BYTES;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
NO_PAGE = OS.memory().allocate(OS.pageSize());
|
|
||||||
NO_BYTES = new VanillaBytes(noBytesStore());
|
|
||||||
IOTools.unmonitor(NO_BYTES);
|
|
||||||
|
|
||||||
} catch ( IllegalArgumentException | IllegalStateException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static <T, B extends BytesStore<B, T>> BytesStore<B, T> noBytesStore() {
|
|
||||||
return NO_BYTES_STORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reserve(ReferenceOwner owner) throws IllegalStateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release(ReferenceOwner owner) throws IllegalStateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void releaseLast(ReferenceOwner id) throws IllegalStateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int refCount() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryReserve(ReferenceOwner owner) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean reservedBy(ReferenceOwner owner) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeByte(long offset, byte i8) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeShort(long offset, short i) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeInt(long offset, int i) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeOrderedInt(long offset, int i) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeLong(long offset, long i) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeOrderedLong(long offset, long i) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeFloat(long offset, float d) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeDouble(long offset, double d) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileByte(long offset, byte i8) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileShort(long offset, short i16) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileInt(long offset, int i32) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileLong(long offset, long i64) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput write(long offsetInRDO, byte[] bytes, int offset, int length) {
|
|
||||||
if (length != 0)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(long offsetInRDO, ByteBuffer bytes, int offset, int length) {
|
|
||||||
if (length != 0)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput write(long writeOffset, RandomDataInput bytes, long readOffset, long length) {
|
|
||||||
if (length != 0)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int peekUnsignedByte(long offset) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readInt(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readLong(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble(long offset) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readVolatileByte(long offset) throws BufferUnderflowException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readVolatileShort(long offset) throws BufferUnderflowException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readVolatileInt(long offset) throws BufferUnderflowException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readVolatileLong(long offset) throws BufferUnderflowException {
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirectMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore copy() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void underlyingObject() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset, long buffer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long copyTo( BytesStore store) {
|
|
||||||
// nothing to copy.
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeWrite(long address, long position, long size) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeRead(long position, long address, long size) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testAndSetInt(long offset, int expected, int value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equalBytes( BytesStore bytesStore, long length) {
|
|
||||||
return length == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(long from, long to, long length) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForRead(long offset) throws BufferUnderflowException {
|
|
||||||
if (offset != 0)
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
return NO_PAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWrite(long offset) throws BufferOverflowException {
|
|
||||||
if (offset != 0)
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
return NO_PAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWritePosition() throws UnsupportedOperationException, BufferOverflowException {
|
|
||||||
return NO_PAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes bytesForWrite() {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sharedMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface OffsetFormat {
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
void append(long offset, Bytes bytes);
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.util.DecoratedBufferOverflowException;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
|
|
||||||
public class OnHeapBytes extends VanillaBytes<byte[]> {
|
|
||||||
public static final int MAX_CAPACITY = Bytes.MAX_HEAP_CAPACITY;
|
|
||||||
private final boolean elastic;
|
|
||||||
private final long capacity;
|
|
||||||
|
|
||||||
public OnHeapBytes( BytesStore bytesStore, boolean elastic) throws IllegalStateException {
|
|
||||||
super(bytesStore);
|
|
||||||
this.elastic = elastic;
|
|
||||||
this.capacity = elastic ? MAX_CAPACITY : bytesStore.capacity();
|
|
||||||
|
|
||||||
writePosition(0);
|
|
||||||
writeLimit(capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isElastic() {
|
|
||||||
return elastic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void writeCheckOffset(long offset, long adding)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (offset >= bytesStore.start()) {
|
|
||||||
long writeEnd = offset + adding;
|
|
||||||
if (writeEnd > writeLimit)
|
|
||||||
throwBeyondWriteLimit(adding, writeEnd);
|
|
||||||
if (writeEnd <= bytesStore.safeLimit()) {
|
|
||||||
return; // do nothing.
|
|
||||||
}
|
|
||||||
checkResize(writeEnd);
|
|
||||||
} else {
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void throwBeyondWriteLimit(long advance, long writeEnd) {
|
|
||||||
throw new DecoratedBufferOverflowException("attempt to write " + advance + " bytes to " + writeEnd + " limit: " + writeLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkResize(long endOfBuffer)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (isElastic())
|
|
||||||
resize(endOfBuffer);
|
|
||||||
else
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// the endOfBuffer is the minimum capacity and one byte more than the last addressable byte.
|
|
||||||
private void resize(long endOfBuffer)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (endOfBuffer < 0)
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
if (endOfBuffer > capacity())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
final long realCapacity = realCapacity();
|
|
||||||
if (endOfBuffer <= realCapacity) {
|
|
||||||
// System.out.println("no resize " + endOfBuffer + " < " + realCapacity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grow by 50%
|
|
||||||
long size0 = Math.max(endOfBuffer, realCapacity * 3 / 2);
|
|
||||||
// Size must not be more than capacity(), it may break some assumptions in BytesStore or elsewhere
|
|
||||||
int size = (int) Math.min(size0, capacity());
|
|
||||||
|
|
||||||
// System.out.println("resize " + endOfBuffer + " to " + size);
|
|
||||||
if (endOfBuffer > 1 << 20)
|
|
||||||
Jvm.warn().on(getClass(), "Resizing buffer was " + realCapacity / 1024 + " KB, " +
|
|
||||||
"needs " + (endOfBuffer - realCapacity) + " bytes more, " +
|
|
||||||
"new-size " + size / 1024 + " KB");
|
|
||||||
HeapBytesStore store;
|
|
||||||
try {
|
|
||||||
store = HeapBytesStore.wrap(new byte[size]);
|
|
||||||
store.reserveTransfer(INIT, this);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
BufferOverflowException boe = new BufferOverflowException();
|
|
||||||
boe.initCause(e);
|
|
||||||
throw boe;
|
|
||||||
}
|
|
||||||
|
|
||||||
BytesStore<Bytes<byte[]>, byte[]> tempStore = this.bytesStore;
|
|
||||||
this.bytesStore.copyTo(store);
|
|
||||||
this.bytesStore(store);
|
|
||||||
try {
|
|
||||||
tempStore.release(this);
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Jvm.debug().on(getClass(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A BytesStore which can point to arbitrary memory.
|
|
||||||
*/
|
|
||||||
public class PointerBytesStore extends NativeBytesStore<Void> {
|
|
||||||
private boolean isPresent = false;
|
|
||||||
|
|
||||||
public PointerBytesStore() {
|
|
||||||
super(NoBytesStore.NO_PAGE, 0, null, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(long address, long capacity) {
|
|
||||||
isPresent = true;
|
|
||||||
setAddress(address);
|
|
||||||
this.limit = maximumLimit = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VanillaBytes<Void> bytesForWrite() throws IllegalStateException {
|
|
||||||
return new VanillaBytes<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long safeLimit() {
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long start() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,207 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceCounted;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
interface RandomCommon extends ReferenceCounted {
|
|
||||||
/**
|
|
||||||
* @return The smallest position allowed in this buffer.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long start() {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the highest limit allowed for this buffer.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long capacity() {
|
|
||||||
return Bytes.MAX_CAPACITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the limit for this buffer without resizing
|
|
||||||
*/
|
|
||||||
default long realCapacity() {
|
|
||||||
return capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The read position must be start() <= readPosition() && readPosition() <= readLimit() && readPosition < safeLimit()
|
|
||||||
*
|
|
||||||
* @return position to read from.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long readPosition() {
|
|
||||||
return start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The read position must be readPosition() <= writePosition() && writePosition() <= writeLimit()
|
|
||||||
*
|
|
||||||
* @return position to write to.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long writePosition() {
|
|
||||||
return start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return How many more bytes can we read.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long readRemaining() {
|
|
||||||
long remaining = readLimit() - readPosition();
|
|
||||||
return remaining;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return How many more bytes can we written.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long writeRemaining() {
|
|
||||||
return writeLimit() - writePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the highest offset or position allowed for this buffer.
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long readLimit() {
|
|
||||||
return realCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
default long writeLimit() {
|
|
||||||
return realCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the underlying addressForRead. This is for expert users only.
|
|
||||||
*
|
|
||||||
* @param offset within this buffer. addressForRead(start()) is the actual addressForRead of the first byte.
|
|
||||||
* @return the underlying addressForRead of the buffer
|
|
||||||
* @throws UnsupportedOperationException if the underlying buffer is on the heap
|
|
||||||
* @throws BufferUnderflowException if the offset is before the start() or the after the capacity()
|
|
||||||
*/
|
|
||||||
long addressForRead(long offset)
|
|
||||||
throws UnsupportedOperationException, BufferUnderflowException;
|
|
||||||
|
|
||||||
default long addressForRead(long offset, int buffer)
|
|
||||||
throws UnsupportedOperationException, BufferUnderflowException {
|
|
||||||
return addressForRead(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the underlying addressForRead. This is for expert users only.
|
|
||||||
*
|
|
||||||
* @param offset within this buffer. addressForRead(start()) is the actual addressForRead of the first byte.
|
|
||||||
* @return the underlying addressForRead of the buffer
|
|
||||||
* @throws UnsupportedOperationException if the underlying buffer is on the heap
|
|
||||||
* @throws BufferOverflowException if the offset is before the start() or the after the capacity()
|
|
||||||
*/
|
|
||||||
long addressForWrite(long offset)
|
|
||||||
throws UnsupportedOperationException, BufferOverflowException;
|
|
||||||
|
|
||||||
long addressForWritePosition()
|
|
||||||
throws UnsupportedOperationException, BufferOverflowException;
|
|
||||||
|
|
||||||
default ByteOrder byteOrder() {
|
|
||||||
return ByteOrder.nativeOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the streaming bytes for reading.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
|
|
||||||
Bytes bytesForRead() throws IllegalStateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the streaming bytes for writing.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
|
|
||||||
Bytes bytesForWrite() throws IllegalStateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a 32-bit CAS at a given offset.
|
|
||||||
*
|
|
||||||
* @param offset to perform CAS
|
|
||||||
* @param expected value
|
|
||||||
* @param value to set
|
|
||||||
* @return true, if successful.
|
|
||||||
*/
|
|
||||||
boolean compareAndSwapInt(long offset, int expected, int value)
|
|
||||||
throws BufferOverflowException;
|
|
||||||
|
|
||||||
void testAndSetInt(long offset, int expected, int value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a 64-bit CAS at a given offset.
|
|
||||||
*
|
|
||||||
* @param offset to perform CAS
|
|
||||||
* @param expected value
|
|
||||||
* @param value to set
|
|
||||||
* @return true, if successful.
|
|
||||||
*/
|
|
||||||
boolean compareAndSwapLong(long offset, long expected, long value)
|
|
||||||
throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a 32-bit float CAS at a given offset.
|
|
||||||
*
|
|
||||||
* @param offset to perform CAS
|
|
||||||
* @param expected value
|
|
||||||
* @param value to set
|
|
||||||
* @return true, if successful.
|
|
||||||
*/
|
|
||||||
default boolean compareAndSwapFloat(long offset, float expected, float value)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
return compareAndSwapInt(offset, Float.floatToRawIntBits(expected), Float.floatToRawIntBits(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a 64-bit double CAS at a given offset.
|
|
||||||
*
|
|
||||||
* @param offset to perform CAS
|
|
||||||
* @param expected value
|
|
||||||
* @param value to set
|
|
||||||
* @return true, if successful.
|
|
||||||
*/
|
|
||||||
default boolean compareAndSwapDouble(long offset, double expected, double value)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
return compareAndSwapLong(offset, Double.doubleToRawLongBits(expected), Double.doubleToRawLongBits(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if these Bytes use shared memory.
|
|
||||||
*/
|
|
||||||
boolean sharedMemory();
|
|
||||||
|
|
||||||
boolean isDirectMemory();
|
|
||||||
}
|
|
|
@ -1,578 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This allows random access to the underling bytes. This instance can be used across threads as it is stateless.
|
|
||||||
* The thread safety of the underlying data depends on how the methods are used.
|
|
||||||
*/
|
|
||||||
public interface RandomDataInput extends RandomCommon {
|
|
||||||
String[] charToString = createCharToString();
|
|
||||||
|
|
||||||
|
|
||||||
static String[] createCharToString() {
|
|
||||||
String[] charToString = new String[256];
|
|
||||||
charToString[0] = "\u0660";
|
|
||||||
for (int i = 1; i < 21; i++)
|
|
||||||
charToString[i] = Character.toString((char) (i + 0x2487));
|
|
||||||
for (int i = ' '; i < 256; i++)
|
|
||||||
charToString[i] = Character.toString((char) i);
|
|
||||||
for (int i = 21; i < ' '; i++)
|
|
||||||
charToString[i] = "\\u00" + Integer.toHexString(i).toUpperCase();
|
|
||||||
for (int i = 0x80; i < 0xA0; i++)
|
|
||||||
charToString[i] = "\\u00" + Integer.toHexString(i).toUpperCase();
|
|
||||||
return charToString;
|
|
||||||
}
|
|
||||||
|
|
||||||
default int peekVolatileInt() throws BufferUnderflowException {
|
|
||||||
return readVolatileInt(readPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read boolean at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the boolean
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default boolean readBoolean(long offset)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesUtil.byteToBoolean(readByte(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read byte at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the byte
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
byte readByte(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an unsigned byte at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the unsigned byte
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default int readUnsignedByte(long offset) throws BufferUnderflowException {
|
|
||||||
return readByte(offset) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an unsigned byte at an offset, or -1
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the unsigned byte or -1
|
|
||||||
*/
|
|
||||||
int peekUnsignedByte(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a short at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the short
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
short readShort(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an unsigned short at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the unsigned short
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default int readUnsignedShort(long offset) throws BufferUnderflowException {
|
|
||||||
return readShort(offset) & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an unsigned int at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the int
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default int readUnsignedInt24(long offset) throws BufferUnderflowException {
|
|
||||||
return readUnsignedShort(offset) | (readUnsignedByte(offset) << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an int at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the int
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
int readInt(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read an unsigned int at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the unsigned int
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
@ForceInline
|
|
||||||
default long readUnsignedInt(long offset) throws BufferUnderflowException {
|
|
||||||
return readInt(offset) & 0xFFFFFFFFL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a long at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the long
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
long readLong(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a float at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the float
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
float readFloat(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a double at an offset
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the double
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
double readDouble(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the byte at an offset and converts it into a printable
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the byte in a printable form.
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default String printable(long offset) throws BufferUnderflowException {
|
|
||||||
return charToString[readUnsignedByte(offset)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a 8-bit byte from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the byte value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
byte readVolatileByte(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a 16-bit short from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the short value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
short readVolatileShort(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a 32-bit int from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the int value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
int readVolatileInt(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a float from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the float value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default float readVolatileFloat(long offset) throws BufferUnderflowException {
|
|
||||||
return Float.intBitsToFloat(readVolatileInt(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a 64-bit long from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the long value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
long readVolatileLong(long offset) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a 64-bit double from memory with a load barrier.
|
|
||||||
*
|
|
||||||
* @param offset to read
|
|
||||||
* @return the double value
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default double readVolatileDouble(long offset) throws BufferUnderflowException {
|
|
||||||
return Double.longBitsToDouble(readVolatileLong(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
default long parseLong(long offset) throws BufferUnderflowException {
|
|
||||||
return BytesInternal.parseLong(this, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* expert level method for copying data to native memory.
|
|
||||||
*
|
|
||||||
* @param position within the ByteStore to copy.
|
|
||||||
* @param address in native memory
|
|
||||||
* @param size in bytes
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
void nativeRead(long position, long address, long size) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a byte[] from memory.
|
|
||||||
*
|
|
||||||
* @return the length actually read.
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default int copyTo( byte[] bytes) throws BufferUnderflowException {
|
|
||||||
int len = (int) Math.min(bytes.length, readRemaining());
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
bytes[i] = readByte(start() + i);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy data from this RandomDataInput to the ByteBuffer. The minimum of {@link #readRemaining()} and
|
|
||||||
* {@link ByteBuffer#remaining()}. Starting from {@link #start()} in this RandomDataInput and from {@link
|
|
||||||
* ByteBuffer#position()} of the given bb. Does NOT change the position or limit or mark of the given ByteBuffer.
|
|
||||||
* Returns the number of the copied bytes.
|
|
||||||
*/
|
|
||||||
default int copyTo( ByteBuffer bb) throws BufferUnderflowException {
|
|
||||||
int pos = bb.position();
|
|
||||||
int len = (int) Math.min(bb.remaining(), readRemaining());
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < len - 7; i += 8)
|
|
||||||
bb.putLong(pos + i, readLong(start() + i));
|
|
||||||
for (; i < len; i++)
|
|
||||||
bb.put(pos + i, readByte(start() + i));
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a long which is zero padded (high bytes) if the available bytes is less than 8.
|
|
||||||
* If the offset is at or beyond the readLimit, this will return 0L.
|
|
||||||
*
|
|
||||||
* @param offset to read from
|
|
||||||
* @return the long which might be padded.
|
|
||||||
*/
|
|
||||||
default long readIncompleteLong(long offset) {
|
|
||||||
long left = readLimit() - offset;
|
|
||||||
long l;
|
|
||||||
try {
|
|
||||||
if (left >= 8)
|
|
||||||
return readLong(offset);
|
|
||||||
if (left == 4)
|
|
||||||
return readInt(offset);
|
|
||||||
l = 0;
|
|
||||||
for (int i = 0, remaining = (int) left; i < remaining; i++) {
|
|
||||||
l |= (long) readUnsignedByte(offset + i) << (i * 8);
|
|
||||||
}
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the actual capacity that can be potentially read.
|
|
||||||
*
|
|
||||||
* @return the actual capacity that can be potentially read.
|
|
||||||
*/
|
|
||||||
long realCapacity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform an atomic add and get operation for a 32-bit int
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default int addAndGetInt(long offset, int adding)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesInternal.addAndGetInt(this, offset, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform an atomic add and get operation for a 64-bit long
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default long addAndGetLong(long offset, long adding)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesInternal.addAndGetLong(this, offset, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform an atomic add and get operation for a 32-bit float
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default float addAndGetFloat(long offset, float adding)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesInternal.addAndGetFloat(this, offset, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform an atomic add and get operation for a 64-bit double
|
|
||||||
*
|
|
||||||
* @param offset to add and get
|
|
||||||
* @param adding value to add, can be 1
|
|
||||||
* @return the sum
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
default double addAndGetDouble(long offset, double adding)
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return BytesInternal.addAndGetDouble(this, offset, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy a sub sequence of bytes as a BytesStore.
|
|
||||||
*
|
|
||||||
* @param start of bytes
|
|
||||||
* @param length of bytes
|
|
||||||
* @return ByteStore copy.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
|
|
||||||
default BytesStore subBytes(long start, long length) throws BufferUnderflowException {
|
|
||||||
return BytesInternal.subBytes(this, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default long findByte(byte stopByte) {
|
|
||||||
return BytesInternal.findByte(this, stopByte);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncates {@code sb} (it must be a {@link StringBuilder} or {@link Bytes}) and reads a char
|
|
||||||
* sequence from the given {@code offset}, encoded as Utf8, into it. Returns offset <i>after</i>
|
|
||||||
* the read Utf8, if a normal char sequence was read, or {@code -1 - offset}, if {@code null}
|
|
||||||
* was observed (in this case, {@code sb} is truncated too, but not updated then, by querying
|
|
||||||
* {@code sb} only this case is indistinguishable from reading an empty char sequence).
|
|
||||||
*
|
|
||||||
* @param offset the offset in this {@code RandomDataInput} to read char sequence from
|
|
||||||
* @param sb the buffer to read char sequence into (truncated first)
|
|
||||||
* @param <ACS> buffer type, must be {@code StringBuilder} or {@code Bytes}
|
|
||||||
* @return offset after the normal read char sequence, or -1 - offset, if char sequence is
|
|
||||||
* {@code null}
|
|
||||||
* @see RandomDataOutput#writeUtf8(long, CharSequence)
|
|
||||||
*/
|
|
||||||
default <ACS extends Appendable & CharSequence> long readUtf8(long offset, ACS sb)
|
|
||||||
throws IORuntimeException, IllegalArgumentException, BufferUnderflowException {
|
|
||||||
AppendableUtil.setLength(sb, 0);
|
|
||||||
// TODO insert some bounds check here
|
|
||||||
|
|
||||||
long utfLen;
|
|
||||||
if ((utfLen = readByte(offset++)) < 0) {
|
|
||||||
utfLen &= 0x7FL;
|
|
||||||
long b;
|
|
||||||
int count = 7;
|
|
||||||
while ((b = readByte(offset++)) < 0) {
|
|
||||||
utfLen |= (b & 0x7FL) << count;
|
|
||||||
count += 7;
|
|
||||||
}
|
|
||||||
if (b != 0) {
|
|
||||||
if (count > 56)
|
|
||||||
throw new IORuntimeException(
|
|
||||||
"Cannot read more than 9 stop bits of positive value");
|
|
||||||
utfLen |= (b << count);
|
|
||||||
} else {
|
|
||||||
if (count > 63)
|
|
||||||
throw new IORuntimeException(
|
|
||||||
"Cannot read more than 10 stop bits of negative value");
|
|
||||||
utfLen = ~utfLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (utfLen == -1)
|
|
||||||
return ~offset;
|
|
||||||
int len = Maths.toUInt31(utfLen);
|
|
||||||
BytesInternal.parseUtf8(this, offset, sb, true, len);
|
|
||||||
return offset + utfLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncates {@code sb} (it must be a {@link StringBuilder} or {@link Bytes}) and reads a char
|
|
||||||
* sequence from the given {@code offset}, encoded as Utf8, into it. Returns offset <i>after</i>
|
|
||||||
* the read Utf8, if a normal char sequence was read, or {@code -1 - offset}, if {@code null}
|
|
||||||
* was observed (in this case, {@code sb} is truncated too, but not updated then, by querying
|
|
||||||
* {@code sb} only this case is indistinguishable from reading an empty char sequence). If
|
|
||||||
* length of Utf8 encoding of the char sequence exceeds {@code maxUtf8Len},
|
|
||||||
* {@code IllegalStateException} is thrown.
|
|
||||||
*
|
|
||||||
* @param offset the offset in this {@code RandomDataInput} to read char sequence from
|
|
||||||
* @param sb the buffer to read char sequence into (truncated first)
|
|
||||||
* @param maxUtf8Len the maximum allowed length of the char sequence in Utf8 encoding
|
|
||||||
* @param <ACS> buffer type, must be {@code StringBuilder} or {@code Bytes}
|
|
||||||
* @return offset after the normal read char sequence, or -1 - offset, if char sequence is
|
|
||||||
* {@code null}
|
|
||||||
* @see RandomDataOutput#writeUtf8Limited(long, CharSequence, int)
|
|
||||||
*/
|
|
||||||
default <ACS extends Appendable & CharSequence> long readUtf8Limited(
|
|
||||||
long offset, ACS sb, int maxUtf8Len)
|
|
||||||
throws IORuntimeException, IllegalArgumentException, BufferUnderflowException,
|
|
||||||
IllegalStateException {
|
|
||||||
AppendableUtil.setLength(sb, 0);
|
|
||||||
// TODO insert some bounds check here
|
|
||||||
|
|
||||||
long utfLen;
|
|
||||||
if ((utfLen = readByte(offset++)) < 0) {
|
|
||||||
utfLen &= 0x7FL;
|
|
||||||
long b;
|
|
||||||
int count = 7;
|
|
||||||
while ((b = readByte(offset++)) < 0) {
|
|
||||||
utfLen |= (b & 0x7FL) << count;
|
|
||||||
count += 7;
|
|
||||||
}
|
|
||||||
if (b != 0) {
|
|
||||||
if (count > 56)
|
|
||||||
throw new IORuntimeException(
|
|
||||||
"Cannot read more than 9 stop bits of positive value");
|
|
||||||
utfLen |= (b << count);
|
|
||||||
} else {
|
|
||||||
if (count > 63)
|
|
||||||
throw new IORuntimeException(
|
|
||||||
"Cannot read more than 10 stop bits of negative value");
|
|
||||||
utfLen = ~utfLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (utfLen == -1)
|
|
||||||
return ~offset;
|
|
||||||
if (utfLen > maxUtf8Len)
|
|
||||||
throw new IllegalStateException("Attempted to read a char sequence of " +
|
|
||||||
"utf8 size " + utfLen + ", when only " + maxUtf8Len + " allowed");
|
|
||||||
BytesInternal.parseUtf8(this, offset, sb, true, (int) utfLen);
|
|
||||||
return offset + utfLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a char sequence from the given {@code offset}, encoded as Utf8. If length of Utf8
|
|
||||||
* encoding of the char sequence exceeds {@code maxUtf8Len}, {@code IllegalStateException}
|
|
||||||
* is thrown.
|
|
||||||
*
|
|
||||||
* @param offset the offset in this {@code RandomDataInput} to read char sequence from
|
|
||||||
* @param maxUtf8Len the maximum allowed length of the char sequence in Utf8 encoding
|
|
||||||
* @return the char sequence was read
|
|
||||||
* @see RandomDataOutput#writeUtf8Limited(long, CharSequence, int)
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String readUtf8Limited(long offset, int maxUtf8Len)
|
|
||||||
throws BufferUnderflowException, IORuntimeException, IllegalArgumentException,
|
|
||||||
IllegalStateException {
|
|
||||||
return BytesInternal.readUtf8(this, offset, maxUtf8Len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares the UTF-8 encoded char sequence, written in this {@code RandomDataInput} at the
|
|
||||||
* given offset, with the given char sequence. Returns {@code true}, if they are equal. Both
|
|
||||||
* char sequences (encoded in bytes and the given) may be {@code null}.
|
|
||||||
*
|
|
||||||
* @param offset the offset in this {@code RandomDataInput} where the char sequence to compare
|
|
||||||
* is written
|
|
||||||
* @param other the second char sequence to compare
|
|
||||||
* @return {@code true} if two char sequences are equal
|
|
||||||
* @throws IORuntimeException if the contents are not a valid string.
|
|
||||||
*/
|
|
||||||
default boolean compareUtf8(long offset, CharSequence other) throws IORuntimeException {
|
|
||||||
return BytesInternal.compareUtf8(this, offset, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default byte[] toByteArray() throws IllegalArgumentException {
|
|
||||||
return BytesInternal.toByteArray(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default long read(long offsetInRDI, byte[] bytes, int offset, int length) {
|
|
||||||
try {
|
|
||||||
int len = (int) Math.min(length, readLimit() - offsetInRDI);
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
bytes[offset + i] = readByte(offsetInRDI + i);
|
|
||||||
return len;
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default ByteBuffer toTemporaryDirectByteBuffer() throws IllegalArgumentException {
|
|
||||||
int len = Maths.toUInt31(readRemaining());
|
|
||||||
try {
|
|
||||||
ByteBuffer bb = ByteBuffer.allocateDirect(len);
|
|
||||||
copyTo(bb);
|
|
||||||
bb.clear();
|
|
||||||
return bb;
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default int fastHash(long offset, int length) throws BufferUnderflowException {
|
|
||||||
long hash = 0;
|
|
||||||
int i = 0;
|
|
||||||
if (length >= 4) {
|
|
||||||
hash = readInt(offset + i);
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
for (; i < length - 3; i += 4) {
|
|
||||||
hash *= 0x6d0f27bd;
|
|
||||||
hash += readInt(offset + i);
|
|
||||||
}
|
|
||||||
if (i < length - 1) {
|
|
||||||
hash *= 0x6d0f27bdL;
|
|
||||||
hash += readShort(offset + i);
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
if (i < length)
|
|
||||||
hash += readByte(offset + i);
|
|
||||||
hash *= 0x855dd4db;
|
|
||||||
return (int) (hash ^ (hash >> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean canReadDirect(long length) {
|
|
||||||
return isDirectMemory() && readRemaining() >= length;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,351 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface RandomDataOutput<R extends RandomDataOutput<R>> extends RandomCommon {
|
|
||||||
/**
|
|
||||||
* Write a byte at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
* @throws IllegalArgumentException if the value cannot be cast to the type without loss.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeByte(long offset, int i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeByte(offset, Maths.toInt8(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an unsigned byte at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
* @throws IllegalArgumentException if the value cannot be cast to the type without loss.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeUnsignedByte(long offset, int i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeByte(offset, (byte) Maths.toUInt8(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a boolean at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param flag the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeBoolean(long offset, boolean flag)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
try {
|
|
||||||
return writeByte(offset, flag ? 'Y' : 'N');
|
|
||||||
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an unsigned byte at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
* @throws IllegalArgumentException if the value cannot be cast to the type without loss.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeUnsignedShort(long offset, int i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeShort(offset, (short) Maths.toUInt16(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an unsigned byte at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
* @throws IllegalArgumentException if the value cannot be cast to the type without loss.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeUnsignedInt(long offset, long i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeInt(offset, (int) Maths.toUInt32(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an unsigned byte at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i8 the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeByte(long offset, byte i8) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a short at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeShort(long offset, short i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default R writeInt24(long offset, int i) throws BufferOverflowException {
|
|
||||||
writeShort(offset, (short) i);
|
|
||||||
return writeByte(offset + 2, (byte) (i >> 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write an int at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeInt(long offset, int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a non stalling write with a store barrier.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i value to write
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeOrderedInt(long offset, int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a non stalling write with a store barrier.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param f value to write
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeOrderedFloat(long offset, float f) throws BufferOverflowException {
|
|
||||||
return writeOrderedInt(offset, Float.floatToRawIntBits(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a long at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeLong(long offset, long i) throws BufferOverflowException, IllegalStateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a non stalling write with a store barrier.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param i value to write
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeOrderedLong(long offset, long i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a non stalling write with a store barrier.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param d value to write
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
|
|
||||||
default R writeOrderedDouble(long offset, double d) throws BufferOverflowException {
|
|
||||||
return writeOrderedLong(offset, Double.doubleToRawLongBits(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a float at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param d the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeFloat(long offset, float d) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a double at an offset.
|
|
||||||
*
|
|
||||||
* @param offset to write to
|
|
||||||
* @param d the value
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R writeDouble(long offset, double d) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
R writeVolatileByte(long offset, byte i8) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
R writeVolatileShort(long offset, short i16) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
R writeVolatileInt(long offset, int i32) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
R writeVolatileLong(long offset, long i64) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default R writeVolatileFloat(long offset, float f) throws BufferOverflowException {
|
|
||||||
return writeVolatileInt(offset, Float.floatToRawIntBits(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default R writeVolatileDouble(long offset, double d) throws BufferOverflowException {
|
|
||||||
return writeVolatileLong(offset, Double.doubleToRawLongBits(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default R write(long offsetInRDO, byte[] bytes) throws BufferOverflowException {
|
|
||||||
return write(offsetInRDO, bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
R write(long offsetInRDO, byte[] bytes, int offset, int length)
|
|
||||||
throws BufferOverflowException;
|
|
||||||
|
|
||||||
void write(long offsetInRDO, ByteBuffer bytes, int offset, int length)
|
|
||||||
throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default R write(long offsetInRDO, BytesStore bytes)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
try {
|
|
||||||
return write(offsetInRDO, bytes, bytes.readPosition(), bytes.readRemaining());
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
R write(long writeOffset, RandomDataInput bytes, long readOffset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero out the bytes between the start and the end.
|
|
||||||
*
|
|
||||||
* @param start index of first byte inclusive
|
|
||||||
* @param end index of last byte exclusive
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the capacity was exceeded
|
|
||||||
*/
|
|
||||||
|
|
||||||
R zeroOut(long start, long end);
|
|
||||||
|
|
||||||
|
|
||||||
default R append(long offset, long value, int digits)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
BytesInternal.append(this, offset, value, digits);
|
|
||||||
return (R) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default R append(long offset, double value, int decimalPlaces, int digits) throws BufferOverflowException {
|
|
||||||
if (decimalPlaces < 20) {
|
|
||||||
double d2 = value * Maths.tens(decimalPlaces);
|
|
||||||
if (d2 <= Long.MAX_VALUE && d2 >= Long.MIN_VALUE) {
|
|
||||||
BytesInternal.appendDecimal(this, Math.round(d2), offset, decimalPlaces, digits);
|
|
||||||
return (R) this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BytesInternal.append((StreamingDataOutput) this, value);
|
|
||||||
return (R) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* expert level method to copy data from native memory into the BytesStore
|
|
||||||
*
|
|
||||||
* @param address in native memory to copy from
|
|
||||||
* @param position in BytesStore to copy to
|
|
||||||
* @param size in bytes
|
|
||||||
*/
|
|
||||||
void nativeWrite(long address, long position, long size) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given {@code cs} to this {@code RandomDataOutput} from the given {@code offset},
|
|
||||||
* in Utf8 format. Returns the offset after the written char sequence.
|
|
||||||
*
|
|
||||||
* @param offset the offset to write char sequence from
|
|
||||||
* @param cs the char sequence to write, could be {@code null}
|
|
||||||
* @return the offset after the char sequence written, in this {@code RandomDataOutput}
|
|
||||||
* @see RandomDataInput#readUtf8(long, Appendable)
|
|
||||||
*/
|
|
||||||
default long writeUtf8(long offset, CharSequence cs) throws BufferOverflowException {
|
|
||||||
return BytesInternal.writeUtf8(this, offset, cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the given {@code cs} to this {@code RandomDataOutput} from the given {@code offset},
|
|
||||||
* in Utf8 format, checking that the utf8 encoding size of the given char sequence is less or
|
|
||||||
* equal to the given {@code maxUtf8Len}, otherwise {@code IllegalArgumentException} is thrown,
|
|
||||||
* and no bytes of this {@code RandomDataOutput} are overwritten. Returns the offset after the
|
|
||||||
* written char sequence.
|
|
||||||
*
|
|
||||||
* @param offset the offset to write char sequence from
|
|
||||||
* @param cs the char sequence to write, could be {@code null}
|
|
||||||
* @param maxUtf8Len the maximum allowed length (in Utf8 encoding) of the given char sequence
|
|
||||||
* @return the offset after the char sequence written, in this {@code RandomDataOutput}
|
|
||||||
* @throws IllegalArgumentException if the given char sequence size in Utf8 encoding exceeds
|
|
||||||
* maxUtf8Len
|
|
||||||
* @see RandomDataInput#readUtf8Limited(long, Appendable, int)
|
|
||||||
* @see RandomDataInput#readUtf8Limited(long, int)
|
|
||||||
*/
|
|
||||||
default long writeUtf8Limited(long offset, CharSequence cs, int maxUtf8Len)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
return BytesInternal.writeUtf8(this, offset, cs, maxUtf8Len);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.annotation.DontChain;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data directly as Bytes.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
@DontChain
|
|
||||||
public interface ReadBytesMarshallable extends CommonMarshallable {
|
|
||||||
/**
|
|
||||||
* Bytes to read. This can be used as a method to implement or as a lambda.
|
|
||||||
*
|
|
||||||
* @param bytes to read.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
void readMarshallable(BytesIn bytes) throws IORuntimeException;
|
|
||||||
}
|
|
|
@ -1,183 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BytesStore to wrap memory mapped data.
|
|
||||||
*/
|
|
||||||
public class ReadOnlyMappedBytesStore extends MappedBytesStore {
|
|
||||||
|
|
||||||
public ReadOnlyMappedBytesStore(ReferenceOwner owner, MappedFile mappedFile, long start, long address, long capacity, long safeCapacity)
|
|
||||||
throws IllegalStateException {
|
|
||||||
super(owner, mappedFile, start, address, capacity, safeCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> zeroOut(long start, long end) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeByte(long offset, byte i8) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeShort(long offset, short i16) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeInt(long offset, int i32) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeLong(long offset, long i64) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeOrderedLong(long offset, long i) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeFloat(long offset, float f) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeDouble(long offset, double d) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeVolatileByte(long offset, byte i8) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeVolatileShort(long offset, short i16) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeVolatileInt(long offset, int i32) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeVolatileLong(long offset, long i64) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> write(long offsetInRDO, byte[] bytes, int offset, int length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(long offsetInRDO, ByteBuffer bytes, int offset, int length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> write(long writeOffset, RandomDataInput bytes, long readOffset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write0(long offsetInRDO, RandomDataInput bytes, long offset, long length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeWrite(long address, long position, long size) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void write8bit(long position, char[] chars, int offset, int length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long appendUTF(long pos, char[] chars, int offset, int length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long appendUtf8(long pos, char[] chars, int offset, int length) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VanillaBytes<Void> bytesForWrite() throws IllegalStateException {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NativeBytesStore<Void> writeOrderedInt(long offset, int i) {
|
|
||||||
throw checkReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IllegalStateException checkReadOnly() throws IllegalStateException {
|
|
||||||
throw new IllegalStateException("Read Only");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean readWrite() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,319 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.ReferenceOwner;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* applied after a Bytes has been released and cannot be used.
|
|
||||||
*
|
|
||||||
* @see NoBytesStore
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public enum ReleasedBytesStore implements BytesStore {
|
|
||||||
RELEASED_BYTES_STORE;
|
|
||||||
|
|
||||||
|
|
||||||
public static <T, B extends BytesStore<B, T>> BytesStore<B, T> releasedBytesStore() {
|
|
||||||
return RELEASED_BYTES_STORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reserve(ReferenceOwner id) throws IllegalStateException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void release(ReferenceOwner id) throws IllegalStateException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int refCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryReserve(ReferenceOwner id) throws IllegalStateException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean reservedBy(ReferenceOwner owner) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void releaseLast(ReferenceOwner id) throws IllegalStateException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeByte(long offset, byte i8) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private IllegalStateException newIllegalStateException() {
|
|
||||||
return new IllegalStateException("released");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeShort(long offset, short i) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeInt(long offset, int i) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeOrderedInt(long offset, int i) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeLong(long offset, long i) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeOrderedLong(long offset, long i) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeFloat(long offset, float d) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeDouble(long offset, double d) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileByte(long offset, byte i8) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileShort(long offset, short i16) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileInt(long offset, int i32) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput writeVolatileLong(long offset, long i64) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput write(long offsetInRDO, byte[] bytes, int offset, int length) {
|
|
||||||
if (length != 0)
|
|
||||||
throw newIllegalStateException();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(long offsetInRDO, ByteBuffer bytes, int offset, int length) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RandomDataOutput write(long writeOffset, RandomDataInput bytes, long readOffset, long length) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int peekUnsignedByte(long offset) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readShort(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readInt(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readLong(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float readFloat(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double readDouble(long offset) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readVolatileByte(long offset) throws BufferUnderflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readVolatileShort(long offset) throws BufferUnderflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readVolatileInt(long offset) throws BufferUnderflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readVolatileLong(long offset) throws BufferUnderflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirectMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore copy() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void underlyingObject() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean inside(long offset, long buffer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long copyTo( BytesStore store) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeWrite(long address, long position, long size) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nativeRead(long position, long address, long size) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testAndSetInt(long offset, int expected, int value) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equalBytes( BytesStore bytesStore, long length) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(long from, long to, long length) {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForRead(long offset) throws BufferUnderflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWrite(long offset) throws BufferOverflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWritePosition() throws UnsupportedOperationException, BufferOverflowException {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes bytesForWrite() {
|
|
||||||
throw newIllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sharedMemory() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
|
|
||||||
public interface RingBufferReader extends RingBufferReaderStats, Closeable {
|
|
||||||
long UNKNOWN_INDEX = -1;
|
|
||||||
|
|
||||||
boolean isEmpty();
|
|
||||||
|
|
||||||
boolean isStopped();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stop the reader. After being stopped, the reader will not block writers.
|
|
||||||
* After being stopped the reader can be re-opened
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the readPosition and readLimit will be adjusted so that the client can read the data
|
|
||||||
*
|
|
||||||
* @param bytes who's byteStore must be the ring buffer,
|
|
||||||
* @return nextReadPosition which should be passed to {@link RingBufferReader#afterRead(long)}
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
long beforeRead(Bytes bytes);
|
|
||||||
|
|
||||||
void afterRead(long next);
|
|
||||||
|
|
||||||
void afterRead(long next, long payloadStart, long underlyingIndex);
|
|
||||||
|
|
||||||
long underlyingIndex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method calls both {@link #beforeRead(Bytes)} and {@link #afterRead(long)}
|
|
||||||
*
|
|
||||||
* @param bytes
|
|
||||||
* @return whether read succeeded
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
boolean read(BytesOut bytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the byteStore which backs the ring buffer
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
BytesStore byteStore();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take reader to just past the end of the RB
|
|
||||||
*/
|
|
||||||
void toEnd();
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
public interface RingBufferReaderStats {
|
|
||||||
|
|
||||||
long getAndClearReadCount();
|
|
||||||
|
|
||||||
long getAndClearMissedReadCount();
|
|
||||||
|
|
||||||
long behind();
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.util.EscapingStopCharTester;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface StopCharTester {
|
|
||||||
/**
|
|
||||||
* Detect which byte stops the string to be parsed
|
|
||||||
* <p>
|
|
||||||
* <p>This should be changed to support char instead.
|
|
||||||
* <p>
|
|
||||||
* <p>Note: for safety reasons, you should stop on a 0 byte or throw an IllegalStateException.
|
|
||||||
*
|
|
||||||
* @param ch to test, 0 should return true or throw an exception.
|
|
||||||
* @return if this byte is a stop character.
|
|
||||||
*/
|
|
||||||
boolean isStopChar(int ch);
|
|
||||||
|
|
||||||
|
|
||||||
default StopCharTester escaping() {
|
|
||||||
return new EscapingStopCharTester(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
public enum StopCharTesters implements StopCharTester {
|
|
||||||
COMMA_STOP {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch < ' ' || ch == ',';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CURLY_STOP {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch < ' ' || ch == '}';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
COMMA_SPACE_STOP {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch <= ' ' || ch == ',';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CONTROL_STOP {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch < ' ';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SPACE_STOP {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return Character.isWhitespace(ch) || ch == 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
QUOTES {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch == '"' || ch <= 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SINGLE_QUOTES {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch == '\'' || ch <= 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
EQUALS {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch == '=' || ch <= 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NUMBER_END {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
switch (ch) {
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case '+':
|
|
||||||
case '-':
|
|
||||||
case '.':
|
|
||||||
case 'E':
|
|
||||||
case 'e':
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NON_ALPHA_DIGIT {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch < '0' || !(Character.isAlphabetic(ch) || Character.isDigit(ch));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ALL {
|
|
||||||
@Override
|
|
||||||
public boolean isStopChar(int ch) {
|
|
||||||
return ch < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.util.EscapingStopCharsTester;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface StopCharsTester {
|
|
||||||
/**
|
|
||||||
* Detect which byte or bytes stops the string to be parsed
|
|
||||||
* <p>
|
|
||||||
* <p>This should be changed to support char instead.
|
|
||||||
* <p>
|
|
||||||
* <p>Note: for safety reasons, you should stop on a 0 byte or throw an IllegalStateException.
|
|
||||||
*
|
|
||||||
* @param ch to test, 0 should return true or throw an exception.
|
|
||||||
* @param ch2 to test, 0 should return true or throw an exception.
|
|
||||||
* @return if this byte is a stop character.
|
|
||||||
*/
|
|
||||||
boolean isStopChar(int ch, int ch2);
|
|
||||||
|
|
||||||
|
|
||||||
default StopCharsTester escaping() {
|
|
||||||
return new EscapingStopCharsTester(this);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public interface StreamingCommon<S extends StreamingCommon<S>> extends RandomCommon {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the readPosition= writePosition = start, writeLimit = capacity
|
|
||||||
*
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
|
|
||||||
S clear();
|
|
||||||
}
|
|
|
@ -1,438 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.UnsafeMemory;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.util.Histogram;
|
|
||||||
import net.openhft.chronicle.core.util.ThrowingConsumer;
|
|
||||||
import net.openhft.chronicle.core.util.ThrowingConsumerNonCapturing;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This data input has a a position() and a limit()
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface StreamingDataInput<S extends StreamingDataInput<S>> extends StreamingCommon<S> {
|
|
||||||
|
|
||||||
S readPosition(long position) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default S readPositionUnlimited(long position) throws BufferUnderflowException {
|
|
||||||
return readLimitToCapacity().readPosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S readPositionRemaining(long position, long remaining) throws BufferUnderflowException {
|
|
||||||
readLimit(position + remaining);
|
|
||||||
return readPosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S readLimit(long limit) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
default S readLimitToCapacity() throws BufferUnderflowException {
|
|
||||||
return readLimit(capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip a number of bytes by moving the readPosition. Must be less than or equal to the readLimit.
|
|
||||||
*
|
|
||||||
* @param bytesToSkip bytes to skip.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferUnderflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
|
|
||||||
S readSkip(long bytesToSkip) throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read skip 1 when you are sure this is safe. Use at your own risk when you find a performance problem.
|
|
||||||
*/
|
|
||||||
void uncheckedReadSkipOne();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read skip -1 when you are sure this is safe. Use at your own risk when you find a performance problem.
|
|
||||||
*/
|
|
||||||
void uncheckedReadSkipBackOne();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a set of actions with a temporary bounds mode.
|
|
||||||
*/
|
|
||||||
default void readWithLength0(long length, ThrowingConsumerNonCapturing<S, IORuntimeException, BytesOut> bytesConsumer, StringBuilder sb, BytesOut toBytes)
|
|
||||||
throws BufferUnderflowException, IORuntimeException {
|
|
||||||
if (length > readRemaining())
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
long limit0 = readLimit();
|
|
||||||
long limit = readPosition() + length;
|
|
||||||
try {
|
|
||||||
readLimit(limit);
|
|
||||||
bytesConsumer.accept((S) this, sb, toBytes);
|
|
||||||
} finally {
|
|
||||||
readLimit(limit0);
|
|
||||||
readPosition(limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform a set of actions with a temporary bounds mode.
|
|
||||||
*/
|
|
||||||
default void readWithLength(long length, ThrowingConsumer<S, IORuntimeException> bytesConsumer)
|
|
||||||
throws BufferUnderflowException, IORuntimeException {
|
|
||||||
if (length > readRemaining())
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
long limit0 = readLimit();
|
|
||||||
long limit = readPosition() + length;
|
|
||||||
try {
|
|
||||||
readLimit(limit);
|
|
||||||
bytesConsumer.accept((S) this);
|
|
||||||
} finally {
|
|
||||||
readLimit(limit0);
|
|
||||||
readPosition(limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default InputStream inputStream() {
|
|
||||||
return new StreamingInputStream(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default long readStopBit() throws IORuntimeException {
|
|
||||||
return BytesInternal.readStopBit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default char readStopBitChar() throws IORuntimeException {
|
|
||||||
return BytesInternal.readStopBitChar(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default double readStopBitDouble() {
|
|
||||||
return BytesInternal.readStopBitDouble(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default double readStopBitDecimal() throws BufferOverflowException {
|
|
||||||
long value = readStopBit();
|
|
||||||
int scale = (int) (Math.abs(value) % 10);
|
|
||||||
value /= 10;
|
|
||||||
return (double) value / Maths.tens(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean readBoolean() {
|
|
||||||
byte b = readByte();
|
|
||||||
return BytesUtil.byteToBoolean(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte readByte();
|
|
||||||
|
|
||||||
default byte rawReadByte() {
|
|
||||||
return readByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
default char readChar() {
|
|
||||||
return readStopBitChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the next unsigned 8 bit value or -1;
|
|
||||||
*/
|
|
||||||
int readUnsignedByte();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the next unsigned 8 bit value or -1;
|
|
||||||
*/
|
|
||||||
int uncheckedReadUnsignedByte();
|
|
||||||
|
|
||||||
short readShort() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
default int readUnsignedShort() throws BufferUnderflowException {
|
|
||||||
return readShort() & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
default int readInt24() throws BufferUnderflowException {
|
|
||||||
return readUnsignedShort() | (readUnsignedByte() << 24 >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
default int readUnsignedInt24() throws BufferUnderflowException {
|
|
||||||
return readUnsignedShort() | (readUnsignedByte() << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
int readInt() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
default int rawReadInt() {
|
|
||||||
return readInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
default long readUnsignedInt()
|
|
||||||
throws BufferUnderflowException {
|
|
||||||
return readInt() & 0xFFFFFFFFL;
|
|
||||||
}
|
|
||||||
|
|
||||||
long readLong() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
default long rawReadLong() {
|
|
||||||
return readLong();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a long using the bytes remaining
|
|
||||||
*/
|
|
||||||
default long readIncompleteLong() {
|
|
||||||
long left = readRemaining();
|
|
||||||
try {
|
|
||||||
if (left >= 8)
|
|
||||||
return readLong();
|
|
||||||
if (left == 4)
|
|
||||||
return readInt();
|
|
||||||
long l = 0;
|
|
||||||
for (int i = 0, remaining = (int) left; i < remaining; i++) {
|
|
||||||
l |= (long) readUnsignedByte() << (i * 8);
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float readFloat() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
double readDouble() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The same as readUTF() except the length is stop bit encoded. This saves one byte for strings shorter than 128
|
|
||||||
* chars. <code>null</code> values are also supported
|
|
||||||
*
|
|
||||||
* @return a Unicode string or <code>null</code> if <code>writeUtf8(null)</code> was called
|
|
||||||
*/
|
|
||||||
|
|
||||||
default String readUtf8()
|
|
||||||
throws BufferUnderflowException, IORuntimeException, IllegalArgumentException {
|
|
||||||
return BytesInternal.readUtf8(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default String readUTFΔ()
|
|
||||||
throws IORuntimeException, BufferUnderflowException, IllegalArgumentException {
|
|
||||||
return BytesInternal.readUtf8(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default String read8bit() throws IORuntimeException, BufferUnderflowException {
|
|
||||||
return BytesInternal.read8bit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The same as readUtf8() except the chars are copied to a truncated StringBuilder.
|
|
||||||
*
|
|
||||||
* @param sb to copy chars to
|
|
||||||
* @return <code>true</code> if there was a String, or <code>false</code> if it was <code>null</code>
|
|
||||||
*/
|
|
||||||
default <ACS extends Appendable & CharSequence> boolean readUtf8( ACS sb)
|
|
||||||
throws IORuntimeException, IllegalArgumentException, BufferUnderflowException {
|
|
||||||
AppendableUtil.setLength(sb, 0);
|
|
||||||
if (readRemaining() <= 0)
|
|
||||||
// TODO throw BufferUnderflowException here? please review
|
|
||||||
return false;
|
|
||||||
long len0 = readStopBit();
|
|
||||||
if (len0 == -1)
|
|
||||||
return false;
|
|
||||||
int len = Maths.toUInt31(len0);
|
|
||||||
if (len > 0)
|
|
||||||
BytesInternal.parseUtf8(this, sb, true, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default <ACS extends Appendable & CharSequence> boolean readUTFΔ( ACS sb)
|
|
||||||
throws IORuntimeException, IllegalArgumentException, BufferUnderflowException {
|
|
||||||
return readUtf8(sb);
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean read8bit( Bytes b)
|
|
||||||
throws BufferUnderflowException, IllegalStateException, BufferOverflowException {
|
|
||||||
b.clear();
|
|
||||||
if (readRemaining() <= 0)
|
|
||||||
return false;
|
|
||||||
long len0 = this.readStopBit();
|
|
||||||
if (len0 == -1)
|
|
||||||
return false;
|
|
||||||
int len = Maths.toUInt31(len0);
|
|
||||||
b.write((BytesStore) this, readPosition(), len);
|
|
||||||
readSkip(len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default <ACS extends Appendable & CharSequence> boolean read8bit( ACS sb)
|
|
||||||
throws IORuntimeException, IllegalArgumentException, BufferUnderflowException {
|
|
||||||
AppendableUtil.setLength(sb, 0);
|
|
||||||
long len0 = BytesInternal.readStopBit(this);
|
|
||||||
if (len0 == -1)
|
|
||||||
return false;
|
|
||||||
int len = Maths.toUInt31(len0);
|
|
||||||
try {
|
|
||||||
AppendableUtil.parse8bit(this, sb, len);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IORuntimeException(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean read8bit( StringBuilder sb)
|
|
||||||
throws IORuntimeException, BufferUnderflowException {
|
|
||||||
sb.setLength(0);
|
|
||||||
long len0 = BytesInternal.readStopBit(this);
|
|
||||||
if (len0 == -1)
|
|
||||||
return false;
|
|
||||||
int len = Maths.toUInt31(len0);
|
|
||||||
try {
|
|
||||||
AppendableUtil.parse8bit(this, sb, len);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IORuntimeException(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default int read( byte[] bytes) {
|
|
||||||
return read(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default int read( byte[] bytes, int off, int len) {
|
|
||||||
long remaining = readRemaining();
|
|
||||||
if (remaining <= 0)
|
|
||||||
return -1;
|
|
||||||
int len2 = (int) Math.min(len, remaining);
|
|
||||||
int i = 0;
|
|
||||||
for (; i < len2 - 7; i += 8)
|
|
||||||
UnsafeMemory.unsafePutLong(bytes, i + off, rawReadLong());
|
|
||||||
for (; i < len2; i++)
|
|
||||||
bytes[off + i] = rawReadByte();
|
|
||||||
return len2;
|
|
||||||
}
|
|
||||||
|
|
||||||
default int read( char[] bytes, int off, int len) {
|
|
||||||
long remaining = readRemaining();
|
|
||||||
if (remaining <= 0)
|
|
||||||
return -1;
|
|
||||||
int len2 = (int) Math.min(len, remaining);
|
|
||||||
for (int i = 0; i < len2; i++)
|
|
||||||
bytes[off + i] = (char) readUnsignedByte();
|
|
||||||
return len2;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void read( ByteBuffer buffer) {
|
|
||||||
for (int i = (int) Math.min(readRemaining(), buffer.remaining()); i > 0; i--)
|
|
||||||
buffer.put(readByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
default void read( Bytes bytes, int length) {
|
|
||||||
int len2 = (int) Math.min(length, readRemaining());
|
|
||||||
int i = 0;
|
|
||||||
for (; i < len2 - 7; i += 8)
|
|
||||||
bytes.rawWriteLong(rawReadLong());
|
|
||||||
for (; i < len2; i++)
|
|
||||||
bytes.rawWriteByte(rawReadByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
default void unsafeReadObject(Object o, int length) {
|
|
||||||
unsafeReadObject(o, (o.getClass().isArray() ? 4 : 0) + Jvm.objectHeaderSize(), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void unsafeReadObject(Object o, int offset, int length) {
|
|
||||||
assert BytesUtil.isTriviallyCopyable(o.getClass(), offset, length);
|
|
||||||
if (readRemaining() < length)
|
|
||||||
throw new BufferUnderflowException();
|
|
||||||
int i = 0;
|
|
||||||
for (; i < length - 7; i += 8)
|
|
||||||
UnsafeMemory.unsafePutLong(o, offset + i, rawReadLong());
|
|
||||||
for (; i < length; i++)
|
|
||||||
UnsafeMemory.unsafePutByte(o, offset + i, rawReadByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
int readVolatileInt() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
long readVolatileLong() throws BufferUnderflowException;
|
|
||||||
|
|
||||||
int peekUnsignedByte();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default <E extends Enum<E>> E readEnum( Class<E> eClass)
|
|
||||||
throws IORuntimeException, BufferUnderflowException {
|
|
||||||
return BytesInternal.readEnum(this, eClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default void parseUTF(Appendable sb, int length)
|
|
||||||
throws IllegalArgumentException, BufferUnderflowException, UTFDataFormatRuntimeException {
|
|
||||||
parseUtf8(sb, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void parseUtf8(Appendable sb, int encodedLength)
|
|
||||||
throws IllegalArgumentException, BufferUnderflowException, UTFDataFormatRuntimeException {
|
|
||||||
parseUtf8(sb, true, encodedLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void parseUtf8(Appendable sb, boolean utf, int length)
|
|
||||||
throws IllegalArgumentException, BufferUnderflowException, UTFDataFormatRuntimeException {
|
|
||||||
AppendableUtil.setLength(sb, 0);
|
|
||||||
BytesInternal.parseUtf8(this, sb, utf, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default long parseHexLong() {
|
|
||||||
return BytesInternal.parseHexLong(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyTo(OutputStream out) throws IOException;
|
|
||||||
|
|
||||||
long copyTo(BytesStore to);
|
|
||||||
|
|
||||||
default void readHistogram( Histogram histogram) {
|
|
||||||
BytesInternal.readHistogram(this, histogram);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void readWithLength(Bytes bytes) {
|
|
||||||
bytes.clear();
|
|
||||||
int length = Maths.toUInt31(readStopBit());
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < length - 7; i++)
|
|
||||||
bytes.writeLong(readLong());
|
|
||||||
for (; i < length; i++)
|
|
||||||
bytes.writeByte(readByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When there is no more data to read, return zero, false and empty string.
|
|
||||||
*
|
|
||||||
* @param lenient if true, return nothing rather than error.
|
|
||||||
*/
|
|
||||||
void lenient(boolean lenient);
|
|
||||||
|
|
||||||
boolean lenient();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,562 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.UnsafeMemory;
|
|
||||||
import net.openhft.chronicle.core.annotation.Java9;
|
|
||||||
import net.openhft.chronicle.core.util.Histogram;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Position based access. Once data has been read, the position() moves.
|
|
||||||
* <p>The use of this instance is single threaded, though the use of the data
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public interface StreamingDataOutput<S extends StreamingDataOutput<S>> extends StreamingCommon<S> {
|
|
||||||
int JAVA9_STRING_CODER_LATIN = 0;
|
|
||||||
int JAVA9_STRING_CODER_UTF16 = 1;
|
|
||||||
|
|
||||||
S writePosition(long position) throws BufferOverflowException;
|
|
||||||
|
|
||||||
S writeLimit(long limit) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skip a number of bytes by moving the writePosition. Must be less than or equal to the writeLimit.
|
|
||||||
*
|
|
||||||
* @param bytesToSkip bytes to skip.
|
|
||||||
* @return this
|
|
||||||
* @throws BufferOverflowException if the offset is outside the limits of the Bytes
|
|
||||||
*/
|
|
||||||
S writeSkip(long bytesToSkip) throws BufferOverflowException;
|
|
||||||
|
|
||||||
default S alignBy(int width) {
|
|
||||||
return writeSkip((-writePosition()) & (width - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Bytes as an OutputStream
|
|
||||||
*/
|
|
||||||
|
|
||||||
default OutputStream outputStream() {
|
|
||||||
return new StreamingOutputStream(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a stop bit encoded long
|
|
||||||
*
|
|
||||||
* @param x long to write
|
|
||||||
* @return this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default S writeStopBit(long x) throws BufferOverflowException {
|
|
||||||
BytesInternal.writeStopBit(this, x);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeStopBit(char x) throws BufferOverflowException {
|
|
||||||
BytesInternal.writeStopBit(this, x);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeStopBit(double d) throws BufferOverflowException {
|
|
||||||
BytesInternal.writeStopBit(this, d);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeStopBitDecimal(double d) throws BufferOverflowException {
|
|
||||||
boolean negative = d < 0;
|
|
||||||
double ad = Math.abs(d);
|
|
||||||
long value;
|
|
||||||
int scale = 0;
|
|
||||||
if ((long) ad == ad) {
|
|
||||||
value = (long) ad * 10;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
double factor = 1;
|
|
||||||
while (scale < 9) {
|
|
||||||
double v = ad * factor;
|
|
||||||
if (v >= 1e14 || (long) v == v)
|
|
||||||
break;
|
|
||||||
factor *= 10;
|
|
||||||
scale++;
|
|
||||||
}
|
|
||||||
value = Math.round(ad * factor);
|
|
||||||
while (scale > 0 && value % 10 == 0) {
|
|
||||||
value /= 10;
|
|
||||||
scale--;
|
|
||||||
}
|
|
||||||
value = value * 10 + scale;
|
|
||||||
}
|
|
||||||
if (negative)
|
|
||||||
value = -value;
|
|
||||||
BytesInternal.writeStopBit(this, value);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the same encoding as <code>writeUTF</code> with the following changes. 1) The length is stop bit encoded
|
|
||||||
* i.e. one byte longer for short strings, but is not limited in length. 2) The string can be null.
|
|
||||||
*
|
|
||||||
* @param cs the string value to be written. Can be null.
|
|
||||||
* @throws BufferOverflowException if there is not enough space left
|
|
||||||
*/
|
|
||||||
|
|
||||||
default S writeUtf8(CharSequence cs)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
BytesInternal.writeUtf8(this, cs);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeUtf8(String s)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
BytesInternal.writeUtf8(this, s);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated(/* to be removed in x.22 */)
|
|
||||||
default S writeUTFΔ(CharSequence cs) throws BufferOverflowException {
|
|
||||||
return writeUtf8(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write8bit(CharSequence cs)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (cs == null)
|
|
||||||
return writeStopBit(-1);
|
|
||||||
|
|
||||||
if (cs instanceof BytesStore)
|
|
||||||
return write8bit((BytesStore) cs);
|
|
||||||
|
|
||||||
if (cs instanceof String)
|
|
||||||
return write8bit((String) cs);
|
|
||||||
|
|
||||||
return write8bit(cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write8bit( CharSequence s, int start, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException, IndexOutOfBoundsException {
|
|
||||||
writeStopBit(length);
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
char c = s.charAt(i + start);
|
|
||||||
rawWriteByte((byte) Maths.toUInt8((int) c));
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write(CharSequence cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IllegalArgumentException {
|
|
||||||
if (cs instanceof BytesStore) {
|
|
||||||
return write((BytesStore) cs);
|
|
||||||
}
|
|
||||||
return write(cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write( CharSequence s, int start, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException, IndexOutOfBoundsException {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
char c = s.charAt(i + start);
|
|
||||||
appendUtf8(c);
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write8bit(String s)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (s == null)
|
|
||||||
writeStopBit(-1);
|
|
||||||
else
|
|
||||||
write8bit(s, 0, (int) Math.min(writeRemaining(), s.length()));
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write8bit(BytesStore bs)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
if (bs == null) {
|
|
||||||
writeStopBit(-1);
|
|
||||||
} else {
|
|
||||||
long offset = bs.readPosition();
|
|
||||||
long readRemaining = Math.min(writeRemaining(), bs.readLimit() - offset);
|
|
||||||
writeStopBit(readRemaining);
|
|
||||||
write(bs, offset, readRemaining);
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeByte(byte i8) throws BufferOverflowException;
|
|
||||||
|
|
||||||
default S rawWriteByte(byte i8) throws BufferOverflowException {
|
|
||||||
return writeByte(i8);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeUnsignedByte(int i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeByte((byte) Maths.toUInt8(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeChar(char ch) {
|
|
||||||
return writeStopBit(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeShort(short i16) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default S writeUnsignedShort(int u16)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeShort((short) Maths.toUInt16(u16));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeInt24(int i) throws BufferOverflowException {
|
|
||||||
writeUnsignedShort((short) i);
|
|
||||||
return writeUnsignedByte((i >>> 16) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeUnsignedInt24(int i) throws BufferOverflowException {
|
|
||||||
writeUnsignedShort((short) i);
|
|
||||||
return writeUnsignedByte(i >>> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeInt(int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
default S rawWriteInt(int i) throws BufferOverflowException {
|
|
||||||
return writeInt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeIntAdv(int i, int advance) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default S writeUnsignedInt(long i)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
return writeInt((int) Maths.toUInt32(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a long
|
|
||||||
*/
|
|
||||||
|
|
||||||
S writeLong(long i64) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a long without a bounds check
|
|
||||||
*/
|
|
||||||
default S rawWriteLong(long i) throws BufferOverflowException {
|
|
||||||
return writeLong(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeLongAdv(long i64, int advance) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
S writeFloat(float f) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
S writeDouble(double d) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
S writeDoubleAndInt(double d, int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write all data or fail.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default S write( RandomDataInput bytes) {
|
|
||||||
assert bytes != this : "you should not write to yourself !";
|
|
||||||
|
|
||||||
try {
|
|
||||||
return write(bytes, bytes.readPosition(), Math.min(writeRemaining(), bytes.readRemaining()));
|
|
||||||
} catch (BufferOverflowException | BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the passed BytesStore
|
|
||||||
*
|
|
||||||
* @param bytes to write
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
default S write( BytesStore bytes) {
|
|
||||||
assert bytes != this : "you should not write to yourself !";
|
|
||||||
|
|
||||||
try {
|
|
||||||
return write(bytes, bytes.readPosition(), Math.min(writeRemaining(), bytes.readRemaining()));
|
|
||||||
} catch (BufferOverflowException | BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return capacity without resize
|
|
||||||
*/
|
|
||||||
long realCapacity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return writeRemaining with resize
|
|
||||||
*/
|
|
||||||
long realWriteRemaining();
|
|
||||||
|
|
||||||
default boolean canWriteDirect(long count) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S writeSome( Bytes bytes) {
|
|
||||||
try {
|
|
||||||
long length = Math.min(bytes.readRemaining(), writeRemaining());
|
|
||||||
if (length + writePosition() >= 1 << 20)
|
|
||||||
length = Math.min(bytes.readRemaining(), realCapacity() - writePosition());
|
|
||||||
write(bytes, bytes.readPosition(), length);
|
|
||||||
if (length == bytes.readRemaining()) {
|
|
||||||
bytes.clear();
|
|
||||||
} else {
|
|
||||||
bytes.readSkip(length);
|
|
||||||
if (bytes.writePosition() > bytes.realCapacity() / 2)
|
|
||||||
bytes.compact();
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
} catch (BufferOverflowException | BufferUnderflowException | IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write all data or fail.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default S write( RandomDataInput bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
BytesInternal.writeFully(bytes, offset, length, this);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write all data or fail.
|
|
||||||
*/
|
|
||||||
|
|
||||||
default S write( BytesStore bytes, long offset, long
|
|
||||||
length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
if (length + writePosition() > capacity())
|
|
||||||
throw new IllegalArgumentException("Cannot write " + length + " bytes as position is " + writePosition() + " and capacity is " + capacity());
|
|
||||||
BytesInternal.writeFully(bytes, offset, length, this);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S write( byte[] bytes) throws BufferOverflowException {
|
|
||||||
write(bytes, 0, bytes.length);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write all data or fail.
|
|
||||||
*/
|
|
||||||
|
|
||||||
S write(byte[] bytes, int offset, int length) throws BufferOverflowException;
|
|
||||||
|
|
||||||
default S unsafeWriteObject(Object o, int length) {
|
|
||||||
return unsafeWriteObject(o, (o.getClass().isArray() ? 4 : 0) + Jvm.objectHeaderSize(), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
default S unsafeWriteObject(Object o, int offset, int length) {
|
|
||||||
int i = 0;
|
|
||||||
for (; i < length - 7; i += 8)
|
|
||||||
writeLong(UnsafeMemory.unsafeGetLong(o, offset + i));
|
|
||||||
for (; i < length; i++)
|
|
||||||
writeByte(UnsafeMemory.unsafeGetByte(o, offset + i));
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeSome(ByteBuffer buffer) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
default S writeBoolean(boolean flag) throws BufferOverflowException {
|
|
||||||
return writeByte(flag ? (byte) 'Y' : (byte) 'N');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
S writeOrderedInt(int i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
|
|
||||||
S writeOrderedLong(long i) throws BufferOverflowException;
|
|
||||||
|
|
||||||
default <E extends Enum<E>> S writeEnum( E e)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
return write8bit(e.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S appendUtf8( CharSequence cs)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
return appendUtf8(cs, 0, cs.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S appendUtf8(int codepoint) throws BufferOverflowException {
|
|
||||||
BytesInternal.appendUtf8Char(this, codepoint);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S appendUtf8(char[] chars, int offset, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
int i;
|
|
||||||
ascii:
|
|
||||||
{
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
if (c > 0x007F)
|
|
||||||
break ascii;
|
|
||||||
writeByte((byte) c);
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
BytesInternal.appendUtf8Char(this, c);
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
default S appendUtf8( CharSequence cs, int offset, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
BytesInternal.appendUtf8(this, cs, offset, length);
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// length is number of characters (not bytes)
|
|
||||||
@Java9
|
|
||||||
|
|
||||||
default S appendUtf8(byte[] bytes, int offset, int length, byte coder)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
if (coder == JAVA9_STRING_CODER_LATIN) {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
byte b = bytes[offset + i];
|
|
||||||
int b2 = (b & 0xFF);
|
|
||||||
BytesInternal.appendUtf8Char(this, b2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert coder == JAVA9_STRING_CODER_UTF16;
|
|
||||||
for (int i = 0; i < 2 * length; i += 2) {
|
|
||||||
byte b1 = bytes[2 * offset + i];
|
|
||||||
byte b2 = bytes[2 * offset + i + 1];
|
|
||||||
|
|
||||||
int uBE = ((b2 & 0xFF) << 8) | b1 & 0xFF;
|
|
||||||
BytesInternal.appendUtf8Char(this, uBE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Java9
|
|
||||||
|
|
||||||
default S appendUtf8(byte[] bytes, int offset, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int b = bytes[offset + i] & 0xFF; // unsigned byte
|
|
||||||
|
|
||||||
if (b >= 0xF0) {
|
|
||||||
int b2 = bytes[offset + i + 1] & 0xFF; // unsigned byte
|
|
||||||
int b3 = bytes[offset + i + 2] & 0xFF; // unsigned byte
|
|
||||||
int b4 = bytes[offset + i + 3] & 0xFF; // unsigned byte
|
|
||||||
this.writeByte((byte) b4);
|
|
||||||
this.writeByte((byte) b3);
|
|
||||||
this.writeByte((byte) b2);
|
|
||||||
this.writeByte((byte) b);
|
|
||||||
|
|
||||||
i += 3;
|
|
||||||
} else if (b >= 0xE0) {
|
|
||||||
int b2 = bytes[offset + i + 1] & 0xFF; // unsigned byte
|
|
||||||
int b3 = bytes[offset + i + 2] & 0xFF; // unsigned byte
|
|
||||||
this.writeByte((byte) b3);
|
|
||||||
this.writeByte((byte) b2);
|
|
||||||
this.writeByte((byte) b);
|
|
||||||
|
|
||||||
i += 2;
|
|
||||||
} else if (b >= 0xC0) {
|
|
||||||
int b2 = bytes[offset + i + 1] & 0xFF; // unsigned byte
|
|
||||||
this.writeByte((byte) b2);
|
|
||||||
this.writeByte((byte) b);
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
this.writeByte((byte) b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (S) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void copyFrom( InputStream input) throws IOException, BufferOverflowException, IllegalArgumentException {
|
|
||||||
BytesInternal.copy(input, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writePositionRemaining(long position, long length) {
|
|
||||||
writeLimit(position + length);
|
|
||||||
writePosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeHistogram( Histogram histogram) {
|
|
||||||
BytesInternal.writeHistogram(this, histogram);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeBigDecimal( BigDecimal bd) {
|
|
||||||
writeBigInteger(bd.unscaledValue());
|
|
||||||
writeStopBit(bd.scale());
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeBigInteger( BigInteger bi) {
|
|
||||||
byte[] bytes = bi.toByteArray();
|
|
||||||
writeStopBit(bytes.length);
|
|
||||||
write(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void writeWithLength(RandomDataInput bytes) {
|
|
||||||
writeStopBit(bytes.readRemaining());
|
|
||||||
write(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class StreamingInputStream extends InputStream {
|
|
||||||
|
|
||||||
private StreamingDataInput in;
|
|
||||||
|
|
||||||
public StreamingInputStream() {
|
|
||||||
this(NoBytesStore.NO_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamingInputStream(StreamingDataInput in) {
|
|
||||||
this.in = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public StreamingInputStream init(StreamingDataInput in) {
|
|
||||||
this.in = in;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long skip(long n) throws IOException {
|
|
||||||
long len = Math.min(in.readRemaining(), n);
|
|
||||||
in.readSkip(len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int available() throws IOException {
|
|
||||||
return (int) Math.min(Integer.MAX_VALUE, in.readRemaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] b, int off, int len) throws IOException {
|
|
||||||
if (len == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int len2 = in.read(b, off, len);
|
|
||||||
return len2 == 0 ? -1 : len2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
return in.readRemaining() > 0 ? in.readUnsignedByte() : -1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class StreamingOutputStream extends OutputStream {
|
|
||||||
private StreamingDataOutput sdo;
|
|
||||||
|
|
||||||
public StreamingOutputStream() {
|
|
||||||
this(NoBytesStore.NO_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamingOutputStream(StreamingDataOutput sdo) {
|
|
||||||
this.sdo = sdo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public StreamingOutputStream init(StreamingDataOutput sdo) {
|
|
||||||
this.sdo = sdo;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(byte[] b, int off, int len) throws IOException {
|
|
||||||
try {
|
|
||||||
sdo.write(b, off, len);
|
|
||||||
|
|
||||||
} catch ( BufferOverflowException | IllegalArgumentException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(int b) throws IOException {
|
|
||||||
try {
|
|
||||||
sdo.writeUnsignedByte(0xff & b);
|
|
||||||
|
|
||||||
} catch ( BufferOverflowException | IllegalArgumentException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class SubBytes<Underlying> extends VanillaBytes<Underlying> {
|
|
||||||
private final long start;
|
|
||||||
private final long capacity;
|
|
||||||
|
|
||||||
public SubBytes( BytesStore bytesStore, long start, long capacity) throws IllegalStateException {
|
|
||||||
super(bytesStore);
|
|
||||||
this.start = start;
|
|
||||||
this.capacity = capacity;
|
|
||||||
clear();
|
|
||||||
readLimit(writeLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubBytes( BytesStore bytesStore) throws IllegalStateException {
|
|
||||||
super(bytesStore);
|
|
||||||
this.start = 0;
|
|
||||||
this.capacity = bytesStore.capacity();
|
|
||||||
clear();
|
|
||||||
readLimit(writeLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long start() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long realCapacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
|
|
||||||
public class UTFDataFormatRuntimeException extends IORuntimeException {
|
|
||||||
public UTFDataFormatRuntimeException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UTFDataFormatRuntimeException(String message, Exception cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,294 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.util.StringUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.core.util.StringUtils.extractBytes;
|
|
||||||
import static net.openhft.chronicle.core.util.StringUtils.extractChars;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast unchecked version of AbstractBytes
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class UncheckedBytes<Underlying>
|
|
||||||
extends AbstractBytes<Underlying> {
|
|
||||||
Bytes underlyingBytes;
|
|
||||||
|
|
||||||
public UncheckedBytes( Bytes underlyingBytes) throws IllegalStateException {
|
|
||||||
super(underlyingBytes.bytesStore(), underlyingBytes.writePosition(), underlyingBytes.writeLimit());
|
|
||||||
this.underlyingBytes = underlyingBytes;
|
|
||||||
readPosition(underlyingBytes.readPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBytes( Bytes bytes) throws IllegalStateException {
|
|
||||||
BytesStore underlyingBytes = bytes.bytesStore();
|
|
||||||
if (bytesStore != underlyingBytes) {
|
|
||||||
bytesStore.release(this);
|
|
||||||
this.bytesStore(underlyingBytes);
|
|
||||||
bytesStore.reserve(this);
|
|
||||||
}
|
|
||||||
readPosition(bytes.readPosition());
|
|
||||||
this.uncheckedWritePosition(bytes.writePosition());
|
|
||||||
this.writeLimit = bytes.writeLimit();
|
|
||||||
|
|
||||||
this.underlyingBytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ensureCapacity(long size) throws IllegalArgumentException {
|
|
||||||
if (size > realCapacity()) {
|
|
||||||
underlyingBytes.ensureCapacity(size);
|
|
||||||
bytesStore(underlyingBytes.bytesStore());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> unchecked(boolean unchecked) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean unchecked() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void writeCheckOffset(long offset, long adding) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void readCheckOffset(long offset, long adding, boolean given) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void prewriteCheckOffset(long offset, long subtracting) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readPosition(long position) {
|
|
||||||
readPosition = position;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readLimit(long limit) {
|
|
||||||
uncheckedWritePosition(limit);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writePosition(long position) {
|
|
||||||
uncheckedWritePosition(position);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readSkip(long bytesToSkip) {
|
|
||||||
readPosition += bytesToSkip;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeSkip(long bytesToSkip) {
|
|
||||||
uncheckedWritePosition(writePosition() + bytesToSkip);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeLimit(long limit) {
|
|
||||||
writeLimit = limit;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore<Bytes<Underlying>, Underlying> copy() {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isElastic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long readOffsetPositionMoved(long adding) {
|
|
||||||
long offset = readPosition;
|
|
||||||
readPosition += adding;
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long writeOffsetPositionMoved(long adding, long advance) {
|
|
||||||
long oldPosition = writePosition();
|
|
||||||
uncheckedWritePosition(writePosition() + advance);
|
|
||||||
return oldPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long prewriteOffsetPositionMoved(long subtracting) throws BufferOverflowException {
|
|
||||||
return readPosition -= subtracting;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( RandomDataInput bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
if (length == 8) {
|
|
||||||
writeLong(bytes.readLong(offset));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
super.write(bytes, offset, length);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Bytes<Underlying> write( BytesStore bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
if (length == 8) {
|
|
||||||
writeLong(bytes.readLong(offset));
|
|
||||||
} else if (bytes.underlyingObject() == null
|
|
||||||
&& bytesStore
|
|
||||||
.isDirectMemory() &&
|
|
||||||
length >= 32) {
|
|
||||||
rawCopy(bytes, offset, length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
super.write(bytes, offset, length);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> append8bit( CharSequence cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
if (cs instanceof RandomDataInput) {
|
|
||||||
return write((RandomDataInput) cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = cs.length();
|
|
||||||
long offset = writeOffsetPositionMoved(length);
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
char c = cs.charAt(i);
|
|
||||||
if (c > 255) c = '?';
|
|
||||||
writeByte(offset, (byte) c);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
long rawCopy( BytesStore bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
long len = Math.min(writeRemaining(), Math.min(bytes.capacity() - offset, length));
|
|
||||||
if (len > 0) {
|
|
||||||
writeCheckOffset(writePosition(), len);
|
|
||||||
this.throwExceptionIfReleased();
|
|
||||||
OS.memory().copyMemory(bytes.addressForRead(offset), addressForWritePosition(), len);
|
|
||||||
writeSkip(len);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeByte(byte i8) throws BufferOverflowException {
|
|
||||||
long offset = writeOffsetPositionMoved(1, 1);
|
|
||||||
bytesStore.writeByte(offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeUtf8(String s) throws BufferOverflowException {
|
|
||||||
if (s == null) {
|
|
||||||
writeStopBit(-1);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (Jvm.isJava9Plus()) {
|
|
||||||
byte[] strBytes = extractBytes(s);
|
|
||||||
byte coder = StringUtils.getStringCoder(s);
|
|
||||||
long utfLength = AppendableUtil.findUtf8Length(strBytes, coder);
|
|
||||||
writeStopBit(utfLength);
|
|
||||||
appendUtf8(strBytes, 0, s.length(), coder);
|
|
||||||
} else {
|
|
||||||
char[] chars = extractChars(s);
|
|
||||||
long utfLength = AppendableUtil.findUtf8Length(chars);
|
|
||||||
writeStopBit(utfLength);
|
|
||||||
if (utfLength == chars.length)
|
|
||||||
append8bit(chars);
|
|
||||||
else
|
|
||||||
appendUtf8(chars, 0, chars.length);
|
|
||||||
}
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append8bit(char[] chars) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
char c = chars[i];
|
|
||||||
bytesStore.writeByte(writePosition++, (byte) c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> appendUtf8(char[] chars, int offset, int length) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
int i;
|
|
||||||
ascii:
|
|
||||||
{
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
if (c > 0x007F)
|
|
||||||
break ascii;
|
|
||||||
bytesStore.writeByte(writePosition++, (byte) c);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
char c = chars[offset + i];
|
|
||||||
BytesInternal.appendUtf8Char(this, c);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(long offsetInRDO, ByteBuffer bytes, int offset, int length) throws BufferOverflowException {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,930 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.algo.BytesStoreHash;
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Memory;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.annotation.ForceInline;
|
|
||||||
import net.openhft.chronicle.core.io.AbstractReferenceCounted;
|
|
||||||
import net.openhft.chronicle.core.io.BackgroundResourceReleaser;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast unchecked version of AbstractBytes
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class UncheckedNativeBytes<Underlying>
|
|
||||||
extends AbstractReferenceCounted
|
|
||||||
implements Bytes<Underlying> {
|
|
||||||
protected final long capacity;
|
|
||||||
|
|
||||||
private final Bytes<Underlying> underlyingBytes;
|
|
||||||
|
|
||||||
protected NativeBytesStore<Underlying> bytesStore;
|
|
||||||
protected long readPosition;
|
|
||||||
protected long writePosition;
|
|
||||||
protected long writeLimit;
|
|
||||||
private int lastDecimalPlaces = 0;
|
|
||||||
|
|
||||||
public UncheckedNativeBytes( Bytes<Underlying> underlyingBytes)
|
|
||||||
throws IllegalStateException {
|
|
||||||
this.underlyingBytes = underlyingBytes;
|
|
||||||
underlyingBytes.reserve(this);
|
|
||||||
this.bytesStore = (NativeBytesStore<Underlying>) underlyingBytes.bytesStore();
|
|
||||||
assert bytesStore.start() == 0;
|
|
||||||
writePosition = underlyingBytes.writePosition();
|
|
||||||
writeLimit = underlyingBytes.writeLimit();
|
|
||||||
readPosition = underlyingBytes.readPosition();
|
|
||||||
capacity = bytesStore.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ensureCapacity(long size) throws IllegalArgumentException {
|
|
||||||
if (size > realCapacity()) {
|
|
||||||
underlyingBytes.ensureCapacity(size);
|
|
||||||
bytesStore = (NativeBytesStore<Underlying>) underlyingBytes.bytesStore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean unchecked() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirectMemory() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> unchecked(boolean unchecked) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void move(long from, long to, long length) {
|
|
||||||
bytesStore.move(from - start(), to - start(), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> compact() {
|
|
||||||
long start = start();
|
|
||||||
long readRemaining = readRemaining();
|
|
||||||
if (readRemaining > 0 && start < readPosition) {
|
|
||||||
bytesStore.move(readPosition, start, readRemaining);
|
|
||||||
readPosition = start;
|
|
||||||
writePosition = readPosition + readRemaining;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readPosition(long position) {
|
|
||||||
readPosition = position;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readLimit(long limit) {
|
|
||||||
writePosition = limit;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writePosition(long position) {
|
|
||||||
writePosition = position;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> readSkip(long bytesToSkip) {
|
|
||||||
readPosition += bytesToSkip;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readVolatileByte(long offset) throws BufferUnderflowException {
|
|
||||||
return bytesStore.readVolatileByte(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short readVolatileShort(long offset) throws BufferUnderflowException {
|
|
||||||
return bytesStore.readVolatileShort(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readVolatileInt(long offset) throws BufferUnderflowException {
|
|
||||||
return bytesStore.readVolatileInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readVolatileLong(long offset) throws BufferUnderflowException {
|
|
||||||
return bytesStore.readVolatileLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void uncheckedReadSkipOne() {
|
|
||||||
readPosition++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void uncheckedReadSkipBackOne() {
|
|
||||||
readPosition--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeSkip(long bytesToSkip) {
|
|
||||||
writePosition += bytesToSkip;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> writeLimit(long limit) {
|
|
||||||
writeLimit = limit;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore<Bytes<Underlying>, Underlying> copy() {
|
|
||||||
throw new UnsupportedOperationException("todo");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isElastic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long readOffsetPositionMoved(long adding) {
|
|
||||||
long offset = readPosition;
|
|
||||||
readPosition += adding;
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long writeOffsetPositionMoved(long adding) {
|
|
||||||
return writeOffsetPositionMoved(adding, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long writeOffsetPositionMoved(long adding, long advance) {
|
|
||||||
long oldPosition = writePosition;
|
|
||||||
long writeEnd = oldPosition + adding;
|
|
||||||
assert writeEnd <= bytesStore.safeLimit();
|
|
||||||
writePosition += advance;
|
|
||||||
return oldPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long prewriteOffsetPositionMoved(long substracting) {
|
|
||||||
return readPosition -= substracting;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( RandomDataInput bytes, long offset, long length)
|
|
||||||
throws BufferUnderflowException, BufferOverflowException {
|
|
||||||
if (length == 8) {
|
|
||||||
writeLong(bytes.readLong(offset));
|
|
||||||
|
|
||||||
} else if (length >= 16 && bytes.isDirectMemory()) {
|
|
||||||
rawCopy(bytes, offset, length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
BytesInternal.writeFully(bytes, offset, length, this);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long rawCopy( RandomDataInput bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
long len = Math.min(writeRemaining(), Math.min(bytes.capacity() - offset, length));
|
|
||||||
if (len > 0) {
|
|
||||||
writeCheckOffset(writePosition(), len);
|
|
||||||
this.throwExceptionIfReleased();
|
|
||||||
OS.memory().copyMemory(bytes.addressForRead(offset), addressForWritePosition(), len);
|
|
||||||
writeSkip(len);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> clear() {
|
|
||||||
readPosition = writePosition = start();
|
|
||||||
writeLimit = capacity();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> clearAndPad(long length) throws BufferOverflowException {
|
|
||||||
if (start() + length > capacity())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
readPosition = writePosition = start() + length;
|
|
||||||
writeLimit = capacity();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readLimit() {
|
|
||||||
return writePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long writeLimit() {
|
|
||||||
return writeLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long realCapacity() {
|
|
||||||
return bytesStore.realCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long realWriteRemaining() {
|
|
||||||
return writeRemaining();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long capacity() {
|
|
||||||
return capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Underlying underlyingObject() {
|
|
||||||
return bytesStore.underlyingObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readPosition() {
|
|
||||||
return readPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long writePosition() {
|
|
||||||
return writePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public boolean compareAndSwapInt(long offset, int expected, int value)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
return bytesStore.compareAndSwapInt(offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testAndSetInt(long offset, int expected, int value) {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
bytesStore.testAndSetInt(offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public boolean compareAndSwapLong(long offset, long expected, long value)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
return bytesStore.compareAndSwapLong(offset, expected, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performRelease() {
|
|
||||||
this.underlyingBytes.release(this);
|
|
||||||
// need to wait as checks rely on this completing.
|
|
||||||
BackgroundResourceReleaser.releasePendingResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readUnsignedByte() {
|
|
||||||
long offset = readOffsetPositionMoved(1);
|
|
||||||
return bytesStore.memory.readByte(bytesStore.address + offset) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int uncheckedReadUnsignedByte() {
|
|
||||||
return readUnsignedByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public byte readByte() {
|
|
||||||
long offset = readOffsetPositionMoved(1);
|
|
||||||
return bytesStore.memory.readByte(bytesStore.address + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int peekUnsignedByte() {
|
|
||||||
try {
|
|
||||||
return readRemaining() > 0 ? bytesStore.readUnsignedByte(readPosition) : -1;
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public short readShort() {
|
|
||||||
long offset = readOffsetPositionMoved(2);
|
|
||||||
return bytesStore.readShort(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int readInt() {
|
|
||||||
long offset = readOffsetPositionMoved(4);
|
|
||||||
return bytesStore.readInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readLong() {
|
|
||||||
long offset = readOffsetPositionMoved(8);
|
|
||||||
return bytesStore.readLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public float readFloat() {
|
|
||||||
long offset = readOffsetPositionMoved(4);
|
|
||||||
return bytesStore.readFloat(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public double readDouble() {
|
|
||||||
long offset = readOffsetPositionMoved(8);
|
|
||||||
return bytesStore.readDouble(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int readVolatileInt() {
|
|
||||||
long offset = readOffsetPositionMoved(4);
|
|
||||||
return bytesStore.readVolatileInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readVolatileLong() {
|
|
||||||
long offset = readOffsetPositionMoved(8);
|
|
||||||
return bytesStore.readVolatileLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeByte(long offset, byte i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 1);
|
|
||||||
bytesStore.writeByte(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeShort(long offset, short i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 2);
|
|
||||||
bytesStore.writeShort(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeInt(long offset, int i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
bytesStore.writeInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeOrderedInt(long offset, int i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
bytesStore.writeOrderedInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeLong(long offset, long i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
bytesStore.writeLong(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeOrderedLong(long offset, long i) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
bytesStore.writeOrderedLong(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeFloat(long offset, float d) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
bytesStore.writeFloat(offset, d);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeDouble(long offset, double d) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
bytesStore.writeDouble(offset, d);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeVolatileByte(long offset, byte i8)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 1);
|
|
||||||
bytesStore.writeVolatileByte(offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeVolatileShort(long offset, short i16)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 2);
|
|
||||||
bytesStore.writeVolatileShort(offset, i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeVolatileInt(long offset, int i32)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 4);
|
|
||||||
bytesStore.writeVolatileInt(offset, i32);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeVolatileLong(long offset, long i64)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offset, 8);
|
|
||||||
bytesStore.writeVolatileLong(offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> write(long offsetInRDO, byte[] bytes, int offset, int length)
|
|
||||||
throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offsetInRDO, length);
|
|
||||||
bytesStore.write(offsetInRDO, bytes, offset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void write(long offsetInRDO, ByteBuffer bytes, int offset, int length) throws BufferOverflowException {
|
|
||||||
writeCheckOffset(offsetInRDO, length);
|
|
||||||
bytesStore.write(offsetInRDO, bytes, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> write(long writeOffset,
|
|
||||||
RandomDataInput bytes, long readOffset, long length)
|
|
||||||
throws BufferUnderflowException, BufferOverflowException {
|
|
||||||
writeCheckOffset(writeOffset, length);
|
|
||||||
bytesStore.write(writeOffset, bytes, readOffset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
void writeCheckOffset(long offset, long adding) throws BufferOverflowException {
|
|
||||||
// assert writeCheckOffset0(offset, adding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public byte readByte(long offset) {
|
|
||||||
return bytesStore.readByte(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readUnsignedByte(long offset) {
|
|
||||||
return bytesStore.memory.readByte(bytesStore.address + offset) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int peekUnsignedByte(long offset) {
|
|
||||||
return offset >= writePosition ? -1 : readByte(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public short readShort(long offset) {
|
|
||||||
return bytesStore.readShort(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public int readInt(long offset) {
|
|
||||||
return bytesStore.readInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public long readLong(long offset) {
|
|
||||||
return bytesStore.readLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public float readFloat(long offset) {
|
|
||||||
return bytesStore.readFloat(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public double readDouble(long offset) {
|
|
||||||
return bytesStore.readDouble(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeByte(byte i8) {
|
|
||||||
long offset = writeOffsetPositionMoved(1);
|
|
||||||
bytesStore.memory.writeByte(bytesStore.address + offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewriteByte(byte i8) {
|
|
||||||
long offset = prewriteOffsetPositionMoved(1);
|
|
||||||
bytesStore.memory.writeByte(bytesStore.address + offset, i8);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeShort(short i16) {
|
|
||||||
long offset = writeOffsetPositionMoved(2);
|
|
||||||
bytesStore.writeShort(offset, i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewriteShort(short i16) {
|
|
||||||
long offset = prewriteOffsetPositionMoved(2);
|
|
||||||
bytesStore.writeShort(offset, i16);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeInt(int i) {
|
|
||||||
long offset = writeOffsetPositionMoved(4);
|
|
||||||
bytesStore.writeInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeIntAdv(int i, int advance) {
|
|
||||||
long offset = writeOffsetPositionMoved(4, advance);
|
|
||||||
bytesStore.writeInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewriteInt(int i) {
|
|
||||||
long offset = prewriteOffsetPositionMoved(4);
|
|
||||||
bytesStore.writeInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeLong(long i64) {
|
|
||||||
long offset = writeOffsetPositionMoved(8);
|
|
||||||
bytesStore.writeLong(offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeLongAdv(long i64, int advance) {
|
|
||||||
long offset = writeOffsetPositionMoved(8, advance);
|
|
||||||
bytesStore.writeLong(offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewriteLong(long i64) {
|
|
||||||
long offset = prewriteOffsetPositionMoved(8);
|
|
||||||
bytesStore.writeLong(offset, i64);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeFloat(float f) {
|
|
||||||
long offset = writeOffsetPositionMoved(4);
|
|
||||||
bytesStore.writeFloat(offset, f);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeDouble(double d) {
|
|
||||||
long offset = writeOffsetPositionMoved(8);
|
|
||||||
bytesStore.writeDouble(offset, d);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeDoubleAndInt(double d, int i) {
|
|
||||||
long offset = writeOffsetPositionMoved(12);
|
|
||||||
bytesStore.writeDouble(offset, d);
|
|
||||||
bytesStore.writeInt(offset + 8, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> write( byte[] bytes, int offset, int length) {
|
|
||||||
if (length + offset > bytes.length)
|
|
||||||
throw new ArrayIndexOutOfBoundsException("bytes.length=" + bytes.length + ", " +
|
|
||||||
"length=" + length + ", offset=" + offset);
|
|
||||||
if (length > writeRemaining())
|
|
||||||
throw new BufferOverflowException();
|
|
||||||
long offsetInRDO = writeOffsetPositionMoved(length);
|
|
||||||
bytesStore.write(offsetInRDO, bytes, offset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewrite( byte[] bytes) {
|
|
||||||
long offsetInRDO = prewriteOffsetPositionMoved(bytes.length);
|
|
||||||
bytesStore.write(offsetInRDO, bytes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> prewrite( BytesStore bytes) {
|
|
||||||
long offsetInRDO = prewriteOffsetPositionMoved(bytes.length());
|
|
||||||
bytesStore.write(offsetInRDO, bytes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeSome( ByteBuffer buffer) {
|
|
||||||
bytesStore.write(writePosition, buffer, buffer.position(), buffer.limit());
|
|
||||||
writePosition += buffer.remaining();
|
|
||||||
assert writePosition <= writeLimit();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeOrderedInt(int i) {
|
|
||||||
long offset = writeOffsetPositionMoved(4);
|
|
||||||
bytesStore.writeOrderedInt(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public Bytes<Underlying> writeOrderedLong(long i) {
|
|
||||||
long offset = writeOffsetPositionMoved(8);
|
|
||||||
bytesStore.writeOrderedLong(offset, i);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForRead(long offset) throws BufferUnderflowException {
|
|
||||||
return bytesStore.addressForRead(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWrite(long offset) throws BufferOverflowException {
|
|
||||||
return bytesStore.addressForWrite(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addressForWritePosition() throws UnsupportedOperationException, BufferOverflowException {
|
|
||||||
return bytesStore.addressForWrite(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return BytesStoreHash.hash32(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof Bytes)) return false;
|
|
||||||
Bytes b2 = (Bytes) obj;
|
|
||||||
long remaining = readRemaining();
|
|
||||||
return b2.readRemaining() == remaining && equalsBytes(b2, remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equalsBytes( Bytes b2, long remaining) {
|
|
||||||
long i = 0;
|
|
||||||
try {
|
|
||||||
for (; i < remaining - 7; i += 8)
|
|
||||||
if (readLong(readPosition() + i) != b2.readLong(b2.readPosition() + i))
|
|
||||||
return false;
|
|
||||||
for (; i < remaining; i++)
|
|
||||||
if (readByte(readPosition() + i) != b2.readByte(b2.readPosition() + i))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw Jvm.rethrow(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return BytesInternal.toString(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lenient(boolean lenient) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean lenient() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void nativeRead(long position, long address, long size) {
|
|
||||||
bytesStore.nativeRead(position, address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@ForceInline
|
|
||||||
public void nativeWrite(long address, long position, long size) {
|
|
||||||
bytesStore.nativeWrite(address, position, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore bytesStore() {
|
|
||||||
return bytesStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int byteCheckSum() throws IORuntimeException {
|
|
||||||
NativeBytesStore bytesStore = (NativeBytesStore) bytesStore();
|
|
||||||
return bytesStore.byteCheckSum(readPosition(), readLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> append8bit( CharSequence cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
if (cs instanceof BytesStore) {
|
|
||||||
return write((BytesStore) cs);
|
|
||||||
}
|
|
||||||
int length = cs.length();
|
|
||||||
long offset = writeOffsetPositionMoved(length);
|
|
||||||
long address = bytesStore.addressForWrite(offset);
|
|
||||||
Memory memory = bytesStore.memory;
|
|
||||||
assert memory != null;
|
|
||||||
try {
|
|
||||||
int i = 0;
|
|
||||||
for (; i < length - 1; i += 2) {
|
|
||||||
char c = cs.charAt(i);
|
|
||||||
char c2 = cs.charAt(i + 1);
|
|
||||||
memory.writeByte(address + i, (byte) c);
|
|
||||||
memory.writeByte(address + i + 1, (byte) c2);
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
char c = cs.charAt(i);
|
|
||||||
memory.writeByte(address + i, (byte) c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
} catch (IndexOutOfBoundsException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> appendUtf8(char[] chars, int offset, int length) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
ensureCapacity(length);
|
|
||||||
NativeBytesStore nbs = this.bytesStore;
|
|
||||||
long position = nbs.appendUtf8(writePosition(), chars, offset, length);
|
|
||||||
writePosition(position);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int lastDecimalPlaces() {
|
|
||||||
return lastDecimalPlaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lastDecimalPlaces(int lastDecimalPlaces) {
|
|
||||||
this.lastDecimalPlaces = Math.max(0, lastDecimalPlaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( RandomDataInput bytes) {
|
|
||||||
assert bytes != this : "you should not write to yourself !";
|
|
||||||
|
|
||||||
try {
|
|
||||||
return write(bytes, bytes.readPosition(), Math.min(writeRemaining(), bytes.readRemaining()));
|
|
||||||
} catch (BufferOverflowException | BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an operation that accepts a single input argument then modifies that same instance.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface UpdateInterceptor {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* modifies {@code t} with changed data
|
|
||||||
*
|
|
||||||
* @param methodName the name of the method
|
|
||||||
* @param t the input argument - for a method call with multiple arguments, the last one is passed
|
|
||||||
* @return whether to proceed. If false, don't write
|
|
||||||
*/
|
|
||||||
boolean update(String methodName, Object t);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,597 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.Jvm;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.Memory;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
import net.openhft.chronicle.core.annotation.Java9;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.util.StringUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.NoBytesStore.noBytesStore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple Bytes implementation which is not Elastic.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public class VanillaBytes<Underlying>
|
|
||||||
extends AbstractBytes<Underlying>
|
|
||||||
implements Byteable<Bytes<Underlying>, Underlying>, Comparable<CharSequence> {
|
|
||||||
|
|
||||||
public VanillaBytes( BytesStore bytesStore) throws IllegalStateException {
|
|
||||||
this(bytesStore, bytesStore.writePosition(), bytesStore.writeLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public VanillaBytes( BytesStore bytesStore, long writePosition, long writeLimit) throws IllegalStateException {
|
|
||||||
super(bytesStore, writePosition, writeLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a non elastic bytes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static VanillaBytes<Void> vanillaBytes() {
|
|
||||||
try {
|
|
||||||
return new VanillaBytes<>(noBytesStore());
|
|
||||||
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Java9
|
|
||||||
private static boolean isEqual0( byte[] bytes, byte coder, NativeBytesStore bs, long address) {
|
|
||||||
|
|
||||||
Memory memory = bs.memory;
|
|
||||||
|
|
||||||
if (coder == 0) {
|
|
||||||
int i = 0;
|
|
||||||
for (; i < bytes.length; i++) {
|
|
||||||
byte b = memory.readByte(address + i);
|
|
||||||
char c = (char) (bytes[i] & 0xFF);
|
|
||||||
if (b != c) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int i = 0;
|
|
||||||
for (; i < bytes.length; i++) {
|
|
||||||
byte b = memory.readByte(address + i);
|
|
||||||
char c = (char) (((bytes[i + 1] & 0xFF) << 8) | (bytes[i] & 0xFF));
|
|
||||||
|
|
||||||
if (b != c) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isEqual0( char[] chars, NativeBytesStore bs, long address) {
|
|
||||||
|
|
||||||
Memory memory = bs.memory;
|
|
||||||
int i = 0;
|
|
||||||
for (; i < chars.length - 3; i += 4) {
|
|
||||||
int b = memory.readInt(address + i);
|
|
||||||
int b0 = b & 0xFF;
|
|
||||||
int b1 = (b >> 8) & 0xFF;
|
|
||||||
int b2 = (b >> 16) & 0xFF;
|
|
||||||
int b3 = (b >> 24) & 0xFF;
|
|
||||||
if (b0 != chars[i] || b1 != chars[i + 1] || b2 != chars[i + 2] || b3 != chars[i + 3])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (; i < chars.length; i++) {
|
|
||||||
int b = memory.readByte(address + i) & 0xFF;
|
|
||||||
if (b != chars[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isEqual1( char[] chars, BytesStore bytesStore, long readPosition) throws BufferUnderflowException {
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
int b = bytesStore.readByte(readPosition + i) & 0xFF;
|
|
||||||
if (b != chars[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Java9
|
|
||||||
private static boolean isEqual1( byte[] bytes, byte coder, BytesStore bytesStore, long readPosition) throws BufferUnderflowException {
|
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
|
||||||
int b = bytesStore.readByte(readPosition + i) & 0xFF;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (coder == 0) {
|
|
||||||
c = (char) (bytes[i] & 0xFF);
|
|
||||||
} else {
|
|
||||||
c = (char) (((bytes[i + 1] & 0xFF) << 8) | (bytes[i] & 0xFF));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b != c)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long readVolatileLong(long offset) throws BufferUnderflowException {
|
|
||||||
readCheckOffset(offset, 8, true);
|
|
||||||
return bytesStore.readVolatileLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bytesStore( BytesStore<Bytes<Underlying>, Underlying> byteStore, long offset, long length)
|
|
||||||
throws IllegalStateException, BufferOverflowException, BufferUnderflowException {
|
|
||||||
setBytesStore(byteStore);
|
|
||||||
// assume its read-only
|
|
||||||
readLimit(offset + length);
|
|
||||||
writeLimit(offset + length);
|
|
||||||
readPosition(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBytesStore( BytesStore<Bytes<Underlying>, Underlying> bytesStore)
|
|
||||||
throws IllegalStateException {
|
|
||||||
if (this.bytesStore != bytesStore) {
|
|
||||||
BytesStore oldBS = this.bytesStore;
|
|
||||||
this.bytesStore(bytesStore);
|
|
||||||
bytesStore.reserve(this);
|
|
||||||
oldBS.release(this);
|
|
||||||
}
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long offset() {
|
|
||||||
return readPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return readRemaining();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isElastic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> bytesForRead() throws IllegalStateException {
|
|
||||||
return isClear()
|
|
||||||
? new VanillaBytes<>(bytesStore, writePosition(), bytesStore.writeLimit())
|
|
||||||
: new SubBytes<>(bytesStore, readPosition(), readLimit());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEqual( String s) {
|
|
||||||
if (s == null || s.length() != readRemaining()) return false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (Jvm.isJava9Plus()) {
|
|
||||||
byte[] bytes = StringUtils.extractBytes(s);
|
|
||||||
byte coder = StringUtils.getStringCoder(s);
|
|
||||||
if (bytesStore instanceof NativeBytesStore) {
|
|
||||||
NativeBytesStore bs = (NativeBytesStore) this.bytesStore;
|
|
||||||
long address = bs.addressForRead(readPosition);
|
|
||||||
return isEqual0(bytes, coder, bs, address);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return isEqual1(bytes, coder, bytesStore, readPosition);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char[] chars = StringUtils.extractChars(s);
|
|
||||||
if (bytesStore instanceof NativeBytesStore) {
|
|
||||||
NativeBytesStore bs = (NativeBytesStore) this.bytesStore;
|
|
||||||
long address = bs.addressForRead(readPosition);
|
|
||||||
return isEqual0(chars, bs, address);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return isEqual1(chars, bytesStore, readPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long realCapacity() {
|
|
||||||
return bytesStore.realCapacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore<Bytes<Underlying>, Underlying> copy() {
|
|
||||||
if (bytesStore.underlyingObject() instanceof ByteBuffer) {
|
|
||||||
try {
|
|
||||||
ByteBuffer bb = ByteBuffer.allocateDirect(Maths.toInt32(readRemaining()));
|
|
||||||
ByteBuffer bbu = (ByteBuffer) bytesStore.underlyingObject();
|
|
||||||
ByteBuffer slice = bbu.slice();
|
|
||||||
slice.position((int) readPosition());
|
|
||||||
slice.limit((int) readLimit());
|
|
||||||
bb.put(slice);
|
|
||||||
bb.clear();
|
|
||||||
return (BytesStore) BytesStore.wrap(bb);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (BytesStore) NativeBytes.copyOf(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( RandomDataInput bytes, long offset, long length)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IllegalArgumentException {
|
|
||||||
optimisedWrite(bytes, offset, length);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void optimisedWrite( RandomDataInput bytes, long offset, long length) {
|
|
||||||
if (length <= safeCopySize() && isDirectMemory() && bytes.isDirectMemory()) {
|
|
||||||
long len = Math.min(writeRemaining(), Math.min(bytes.capacity() - offset, length));
|
|
||||||
if (len > 0) {
|
|
||||||
writeCheckOffset(writePosition(), len);
|
|
||||||
long address = bytes.addressForRead(offset);
|
|
||||||
long address2 = addressForWritePosition();
|
|
||||||
assert address != 0;
|
|
||||||
assert address2 != 0;
|
|
||||||
OS.memory().copyMemory(address, address2, len);
|
|
||||||
writeSkip(len);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.write(bytes, offset, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(long position, CharSequence str, int offset, int length)
|
|
||||||
throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
|
|
||||||
ensureCapacity(length);
|
|
||||||
if (offset + length > str.length())
|
|
||||||
throw new IllegalArgumentException("offset=" + offset + " + length=" + length + " > str.length =" + str.length());
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
bytesStore.writeByte(position + i, str.charAt(offset + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public VanillaBytes append( CharSequence str, int start, int end) throws IndexOutOfBoundsException {
|
|
||||||
assert end > start : "end=" + end + ",start=" + start;
|
|
||||||
try {
|
|
||||||
if (isDirectMemory()) {
|
|
||||||
if (str instanceof BytesStore) {
|
|
||||||
|
|
||||||
write((BytesStore) str, (long) start, end - start);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if (str instanceof String) {
|
|
||||||
if (Jvm.isJava9Plus()) {
|
|
||||||
byte coder = StringUtils.getStringCoder((String) str);
|
|
||||||
appendUtf8(StringUtils.extractBytes((String) str), start, end - start, coder);
|
|
||||||
} else {
|
|
||||||
appendUtf8(StringUtils.extractChars((String) str), start, end - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.append(str, start, end);
|
|
||||||
return this;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IndexOutOfBoundsException(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public VanillaBytes appendUtf8( CharSequence str) throws BufferOverflowException {
|
|
||||||
try {
|
|
||||||
if (isDirectMemory()) {
|
|
||||||
if (str instanceof BytesStore) {
|
|
||||||
write((BytesStore) str, 0L, str.length());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
if (str instanceof String) {
|
|
||||||
if (Jvm.isJava9Plus()) {
|
|
||||||
String str1 = (String) str;
|
|
||||||
byte coder = StringUtils.getStringCoder(str1);
|
|
||||||
appendUtf8(StringUtils.extractBytes(str1), 0, str.length(), coder);
|
|
||||||
} else {
|
|
||||||
appendUtf8(StringUtils.extractChars((String) str), 0, str.length());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.append(str, 0, str.length());
|
|
||||||
return this;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
BufferOverflowException e2 = new BufferOverflowException();
|
|
||||||
e2.initCause(e);
|
|
||||||
throw e2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> append8bit( CharSequence cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
if (cs instanceof RandomDataInput)
|
|
||||||
return write((RandomDataInput) cs);
|
|
||||||
|
|
||||||
if (isDirectMemory() && cs instanceof String)
|
|
||||||
return append8bitNBS_S((String) cs);
|
|
||||||
return append8bit0(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> append8bit( BytesStore bs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
long remaining = bs.readLimit() - bs.readPosition();
|
|
||||||
return write(bs, 0L, remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> write( BytesStore bytes, long offset, long length) throws BufferOverflowException, BufferUnderflowException {
|
|
||||||
if (bytes.canReadDirect(length) && canWriteDirect(length) && length == (int) length) {
|
|
||||||
long wAddr = addressForWritePosition();
|
|
||||||
writeSkip(length);
|
|
||||||
long rAddr = bytes.addressForRead(offset);
|
|
||||||
BytesInternal.copyMemory(rAddr, wAddr, (int) length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
BytesInternal.writeFully(bytes, offset, length, this);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
|
|
||||||
public Bytes<Underlying> append8bit( String cs)
|
|
||||||
throws BufferOverflowException, BufferUnderflowException, IndexOutOfBoundsException {
|
|
||||||
if (isDirectMemory())
|
|
||||||
return append8bitNBS_S(cs);
|
|
||||||
return append8bit0(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Bytes<Underlying> append8bitNBS_S( String s) throws BufferOverflowException {
|
|
||||||
int length = s.length();
|
|
||||||
long offset = writeOffsetPositionMoved(length); // can re-assign the byteStore if not large enough.
|
|
||||||
NativeBytesStore bytesStore = (NativeBytesStore) this.bytesStore;
|
|
||||||
final long address = bytesStore.address + bytesStore.translate(offset);
|
|
||||||
final Memory memory = bytesStore.memory;
|
|
||||||
|
|
||||||
if (memory == null)
|
|
||||||
bytesStore.throwExceptionIfReleased();
|
|
||||||
|
|
||||||
if (Jvm.isJava9Plus()) {
|
|
||||||
final byte[] chars = StringUtils.extractBytes(s);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
memory.writeByte(address + i, chars[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final char[] chars = StringUtils.extractChars(s);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < length - 3; i += 4) {
|
|
||||||
int c0 = chars[i] & 0xFF;
|
|
||||||
int c1 = chars[i + 1] & 0xFF;
|
|
||||||
int c2 = chars[i + 2] & 0xFF;
|
|
||||||
int c3 = chars[i + 3] & 0xFF;
|
|
||||||
memory.writeInt(address + i, c0 | (c1 << 8) | (c2 << 16) | (c3 << 24));
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
int c0 = chars[i];
|
|
||||||
memory.writeByte(address + i, (byte) c0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return bytesStore instanceof NativeBytesStore
|
|
||||||
? toString2((NativeBytesStore) bytesStore)
|
|
||||||
: toString0();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toString2( NativeBytesStore bytesStore) {
|
|
||||||
int length = (int)
|
|
||||||
Math.min(Bytes.MAX_HEAP_CAPACITY, readRemaining());
|
|
||||||
char[] chars = new char[length];
|
|
||||||
final Memory memory = bytesStore.memory;
|
|
||||||
final long address = bytesStore.address + bytesStore.translate(readPosition());
|
|
||||||
for (int i = 0; i < length && i < realCapacity(); i++)
|
|
||||||
chars[i] = (char) (memory.readByte(address + i) & 0xFF);
|
|
||||||
|
|
||||||
return StringUtils.newString(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected String toString0() {
|
|
||||||
int length = (int) Math.min(Bytes.MAX_HEAP_CAPACITY, readRemaining());
|
|
||||||
char[] chars = new char[length];
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
chars[i] = (char) (bytesStore.readByte(readPosition() + i) & 0xFF);
|
|
||||||
}
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
return StringUtils.newString(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Bytes<Underlying> append8bit0( CharSequence cs) throws BufferOverflowException, IndexOutOfBoundsException {
|
|
||||||
int length = cs.length();
|
|
||||||
long offset = writeOffsetPositionMoved(length);
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
char c = cs.charAt(i);
|
|
||||||
if (c > 255) c = '?';
|
|
||||||
bytesStore.writeByte(offset + i, (byte) c);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equalBytes( BytesStore bytesStore, long length) throws BufferUnderflowException {
|
|
||||||
if (isDirectMemory() &&
|
|
||||||
bytesStore instanceof VanillaBytes &&
|
|
||||||
bytesStore.isDirectMemory()) {
|
|
||||||
VanillaBytes b2 = (VanillaBytes) bytesStore;
|
|
||||||
NativeBytesStore nbs0 = (NativeBytesStore) this.bytesStore;
|
|
||||||
NativeBytesStore nbs2 = (NativeBytesStore) b2.bytesStore();
|
|
||||||
long i = 0;
|
|
||||||
for (; i < length - 7; i += 8) {
|
|
||||||
long addr0 = nbs0.address + readPosition() - nbs0.start() + i;
|
|
||||||
long addr2 = nbs2.address + b2.readPosition() - nbs2.start() + i;
|
|
||||||
long l0 = nbs0.memory.readLong(addr0);
|
|
||||||
long l2 = nbs2.memory.readLong(addr2);
|
|
||||||
if (l0 != l2)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (; i < length; i++) {
|
|
||||||
long offset2 = readPosition() + i - nbs0.start();
|
|
||||||
long offset21 = b2.readPosition() + i - nbs2.start();
|
|
||||||
byte b0 = nbs0.memory.readByte(nbs0.address + offset2);
|
|
||||||
byte b1 = nbs2.memory.readByte(nbs2.address + offset21);
|
|
||||||
if (b0 != b1)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.equalBytes(bytesStore, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void read8Bit(char[] chars, int length) {
|
|
||||||
if (isDirectMemory()) {
|
|
||||||
long position = readPosition();
|
|
||||||
NativeBytesStore nbs = (NativeBytesStore) bytesStore();
|
|
||||||
nbs.read8bit(position, chars, length);
|
|
||||||
} else {
|
|
||||||
long pos = this.readPosition();
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
chars[i] = (char) this.readUnsignedByte(pos + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: protected?
|
|
||||||
@Override
|
|
||||||
public int byteCheckSum(int start, int end) throws IORuntimeException {
|
|
||||||
byte b = 0;
|
|
||||||
// the below cast is safe as should only be called from net.openhft.chronicle.bytes.AbstractBytes.byteCheckSum(long, long)
|
|
||||||
NativeBytesStore bytesStore = (NativeBytesStore) bytesStore();
|
|
||||||
Memory memory = bytesStore.memory;
|
|
||||||
assert memory != null;
|
|
||||||
long addr = bytesStore.addressForRead(start);
|
|
||||||
int i = 0, len = end - start;
|
|
||||||
for (; i < len - 3; i += 4) {
|
|
||||||
b += memory.readByte(addr + i)
|
|
||||||
+ memory.readByte(addr + i + 1)
|
|
||||||
+ memory.readByte(addr + i + 2)
|
|
||||||
+ memory.readByte(addr + i + 3);
|
|
||||||
}
|
|
||||||
for (; i < len; i++) {
|
|
||||||
b += memory.readByte(addr + i);
|
|
||||||
}
|
|
||||||
return b & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bytes<Underlying> appendUtf8(char[] chars, int offset, int length) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
ensureCapacity(length);
|
|
||||||
if (bytesStore instanceof NativeBytesStore) {
|
|
||||||
NativeBytesStore nbs = (NativeBytesStore) this.bytesStore;
|
|
||||||
long position = nbs.appendUtf8(writePosition(), chars, offset, length);
|
|
||||||
writePosition(position);
|
|
||||||
} else {
|
|
||||||
super.appendUtf8(chars, offset, length);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuffer toTemporaryDirectByteBuffer() throws IllegalArgumentException {
|
|
||||||
if (isClear())
|
|
||||||
return bytesStore.toTemporaryDirectByteBuffer();
|
|
||||||
return super.toTemporaryDirectByteBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read( byte[] bytes) {
|
|
||||||
int len = (int) Math.min(bytes.length, readRemaining());
|
|
||||||
if (bytesStore instanceof NativeBytesStore) {
|
|
||||||
NativeBytesStore nbs = (NativeBytesStore) this.bytesStore;
|
|
||||||
long len2 = nbs.read(readPosition(), bytes, 0, len);
|
|
||||||
try {
|
|
||||||
readSkip(len2);
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return (int) (len2);
|
|
||||||
}
|
|
||||||
return super.read(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo( CharSequence cs) {
|
|
||||||
long len1 = readRemaining();
|
|
||||||
int len2 = cs.length();
|
|
||||||
long lim = Math.min(len1, len2);
|
|
||||||
|
|
||||||
int k = 0;
|
|
||||||
while (k < lim) {
|
|
||||||
char c1 = bytesStore.charAt(k);
|
|
||||||
char c2 = cs.charAt(k);
|
|
||||||
if (c1 != c2) {
|
|
||||||
return c1 - c2;
|
|
||||||
}
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
return (int) (len1 - len2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.core.annotation.DontChain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data directly as Bytes.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@FunctionalInterface
|
|
||||||
@DontChain
|
|
||||||
public interface WriteBytesMarshallable extends CommonMarshallable {
|
|
||||||
/**
|
|
||||||
* Write to Bytes. This can be used as an interface to extend or a lambda
|
|
||||||
*
|
|
||||||
* @param bytes to write to.
|
|
||||||
*/
|
|
||||||
void writeMarshallable(BytesOut bytes);
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes.algo;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.bytes.NativeBytesStore;
|
|
||||||
|
|
||||||
import java.util.function.ToLongFunction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple function to derive a long hash from a BytesStore
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public interface BytesStoreHash<B extends BytesStore> extends ToLongFunction<B> {
|
|
||||||
static long hash( BytesStore b) {
|
|
||||||
return b.isDirectMemory() && b.bytesStore() instanceof NativeBytesStore
|
|
||||||
? OptimisedBytesStoreHash.INSTANCE.applyAsLong(b)
|
|
||||||
: VanillaBytesStoreHash.INSTANCE.applyAsLong(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long hash( BytesStore b, long length) {
|
|
||||||
return b.isDirectMemory() && b.bytesStore() instanceof NativeBytesStore
|
|
||||||
? OptimisedBytesStoreHash.INSTANCE.applyAsLong(b, length)
|
|
||||||
: VanillaBytesStoreHash.INSTANCE.applyAsLong(b, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hash32(BytesStore b) {
|
|
||||||
long hash = hash(b);
|
|
||||||
return (int) (hash ^ (hash >>> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hash32( BytesStore b, int length) {
|
|
||||||
long hash = hash(b, length);
|
|
||||||
return (int) (hash ^ (hash >>> 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
long applyAsLong(BytesStore bytes, long length);
|
|
||||||
}
|
|
|
@ -1,274 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes.algo;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.bytes.NativeBytesStore;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import net.openhft.chronicle.core.Memory;
|
|
||||||
import net.openhft.chronicle.core.OS;
|
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.algo.VanillaBytesStoreHash.*;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public enum OptimisedBytesStoreHash implements BytesStoreHash<BytesStore> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
|
|
||||||
public static final Memory MEMORY = OS.memory();
|
|
||||||
public static final boolean IS_LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
|
|
||||||
private static final int TOP_BYTES = IS_LITTLE_ENDIAN ? 4 : 0;
|
|
||||||
|
|
||||||
static long applyAsLong1to7( BytesStore store, int remaining) {
|
|
||||||
final long address = store.addressForRead(store.readPosition());
|
|
||||||
|
|
||||||
return hash(readIncompleteLong(address, remaining));
|
|
||||||
}
|
|
||||||
|
|
||||||
static long applyAsLong8( BytesStore store) {
|
|
||||||
final long address = store.addressForRead(store.readPosition());
|
|
||||||
|
|
||||||
return hash0(MEMORY.readLong(address), MEMORY.readInt(address + TOP_BYTES));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long hash(long l) {
|
|
||||||
return hash0(l, l >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long hash0(long l, long hi) {
|
|
||||||
return agitate(l * K0 + hi * K1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long applyAsLong9to16( BytesStore store, int remaining) {
|
|
||||||
final NativeBytesStore bytesStore = (NativeBytesStore) store.bytesStore();
|
|
||||||
final long address = bytesStore.addressForRead(store.readPosition());
|
|
||||||
long h0 = (long) remaining * K0;
|
|
||||||
|
|
||||||
int left = remaining;
|
|
||||||
long addrI = address;
|
|
||||||
|
|
||||||
long l0 = readIncompleteLong(addrI, left);
|
|
||||||
int l0a = (int) (l0 >> 32);
|
|
||||||
long l1 = readIncompleteLong(addrI + 8, left - 8);
|
|
||||||
int l1a = (int) (l1 >> 32);
|
|
||||||
final long l2 = 0;
|
|
||||||
final int l2a = 0;
|
|
||||||
final long l3 = 0;
|
|
||||||
final int l3a = 0;
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
long h1 = (l1 + l2a - l3a) * M1;
|
|
||||||
long h2 = (l2 + l3a - l0a) * M2;
|
|
||||||
long h3 = (l3 + l0a - l1a) * M3;
|
|
||||||
|
|
||||||
return agitate(h0) ^ agitate(h1)
|
|
||||||
^ agitate(h2) ^ agitate(h3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long applyAsLong17to32( BytesStore store, int remaining) {
|
|
||||||
final NativeBytesStore bytesStore = (NativeBytesStore) store.bytesStore();
|
|
||||||
final long address = bytesStore.addressForRead(store.readPosition());
|
|
||||||
long h0 = (long) remaining * K0;
|
|
||||||
|
|
||||||
int left = remaining;
|
|
||||||
long addrI = address;
|
|
||||||
|
|
||||||
long l0 = MEMORY.readLong(addrI);
|
|
||||||
int l0a = MEMORY.readInt(addrI + TOP_BYTES);
|
|
||||||
long l1 = MEMORY.readLong(addrI + 8);
|
|
||||||
int l1a = MEMORY.readInt(addrI + 8 + TOP_BYTES);
|
|
||||||
long l2 = readIncompleteLong(addrI + 16, left - 16);
|
|
||||||
int l2a = (int) (l2 >> 32);
|
|
||||||
long l3 = readIncompleteLong(addrI + 24, left - 24);
|
|
||||||
int l3a = (int) (l3 >> 32);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
long h1 = (l1 + l2a - l3a) * M1;
|
|
||||||
long h2 = (l2 + l3a - l0a) * M2;
|
|
||||||
long h3 = (l3 + l0a - l1a) * M3;
|
|
||||||
|
|
||||||
return agitate(h0) ^ agitate(h1)
|
|
||||||
^ agitate(h2) ^ agitate(h3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long applyAsLong32bytesMultiple( BytesStore store, int remaining) {
|
|
||||||
final NativeBytesStore bytesStore = (NativeBytesStore) store.bytesStore();
|
|
||||||
final long address = bytesStore.addressForRead(store.readPosition());
|
|
||||||
long h0 = remaining * K0, h1 = 0, h2 = 0, h3 = 0;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < remaining - 31; i += 32) {
|
|
||||||
if (i > 0) {
|
|
||||||
h0 *= K0;
|
|
||||||
h1 *= K1;
|
|
||||||
h2 *= K2;
|
|
||||||
h3 *= K3;
|
|
||||||
}
|
|
||||||
long addrI = address + i;
|
|
||||||
long l0 = MEMORY.readLong(addrI);
|
|
||||||
int l0a = MEMORY.readInt(addrI + TOP_BYTES);
|
|
||||||
long l1 = MEMORY.readLong(addrI + 8);
|
|
||||||
int l1a = MEMORY.readInt(addrI + 8 + TOP_BYTES);
|
|
||||||
long l2 = MEMORY.readLong(addrI + 16);
|
|
||||||
int l2a = MEMORY.readInt(addrI + 16 + TOP_BYTES);
|
|
||||||
long l3 = MEMORY.readLong(addrI + 24);
|
|
||||||
int l3a = MEMORY.readInt(addrI + 24 + TOP_BYTES);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return agitate(h0) ^ agitate(h1)
|
|
||||||
^ agitate(h2) ^ agitate(h3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long applyAsLongAny( BytesStore store, long remaining) {
|
|
||||||
final NativeBytesStore bytesStore = (NativeBytesStore) store.bytesStore();
|
|
||||||
final long address = bytesStore.addressForRead(store.readPosition());
|
|
||||||
long h0 = remaining * K0, h1 = 0, h2 = 0, h3 = 0;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < remaining - 31; i += 32) {
|
|
||||||
if (i > 0) {
|
|
||||||
h0 *= K0;
|
|
||||||
h1 *= K1;
|
|
||||||
h2 *= K2;
|
|
||||||
h3 *= K3;
|
|
||||||
}
|
|
||||||
long addrI = address + i;
|
|
||||||
long l0 = MEMORY.readLong(addrI);
|
|
||||||
int l0a = MEMORY.readInt(addrI + TOP_BYTES);
|
|
||||||
long l1 = MEMORY.readLong(addrI + 8);
|
|
||||||
int l1a = MEMORY.readInt(addrI + 8 + TOP_BYTES);
|
|
||||||
long l2 = MEMORY.readLong(addrI + 16);
|
|
||||||
int l2a = MEMORY.readInt(addrI + 16 + TOP_BYTES);
|
|
||||||
long l3 = MEMORY.readLong(addrI + 24);
|
|
||||||
int l3a = MEMORY.readInt(addrI + 24 + TOP_BYTES);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
}
|
|
||||||
long left = remaining - i;
|
|
||||||
if (left > 0) {
|
|
||||||
if (i > 0) {
|
|
||||||
h0 *= K0;
|
|
||||||
h1 *= K1;
|
|
||||||
h2 *= K2;
|
|
||||||
h3 *= K3;
|
|
||||||
}
|
|
||||||
long addrI = address + i;
|
|
||||||
if (left <= 16) {
|
|
||||||
|
|
||||||
long l0 = readIncompleteLong(addrI, (int) left);
|
|
||||||
int l0a = (int) (l0 >> 32);
|
|
||||||
long l1 = readIncompleteLong(addrI + 8, (int) (left - 8));
|
|
||||||
int l1a = (int) (l1 >> 32);
|
|
||||||
final long l2 = 0;
|
|
||||||
final int l2a = 0;
|
|
||||||
final long l3 = 0;
|
|
||||||
final int l3a = 0;
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
long l0 = MEMORY.readLong(addrI);
|
|
||||||
int l0a = MEMORY.readInt(addrI + TOP_BYTES);
|
|
||||||
long l1 = MEMORY.readLong(addrI + 8);
|
|
||||||
int l1a = MEMORY.readInt(addrI + 8 + TOP_BYTES);
|
|
||||||
long l2 = readIncompleteLong(addrI + 16, (int) (left - 16));
|
|
||||||
int l2a = (int) (l2 >> 32);
|
|
||||||
long l3 = readIncompleteLong(addrI + 24, (int) (left - 24));
|
|
||||||
int l3a = (int) (l3 >> 32);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return agitate(h0) ^ agitate(h1)
|
|
||||||
^ agitate(h2) ^ agitate(h3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static long readIncompleteLong(long address, int len) {
|
|
||||||
switch (len) {
|
|
||||||
case 1:
|
|
||||||
return MEMORY.readByte(address);
|
|
||||||
case 2:
|
|
||||||
return MEMORY.readShort(address);
|
|
||||||
case 3:
|
|
||||||
return IS_LITTLE_ENDIAN
|
|
||||||
? (MEMORY.readShort(address) & 0xFFFF) + ((MEMORY.readByte(address + 2) & 0xFF) << 16)
|
|
||||||
: ((MEMORY.readShort(address) & 0xFFFF) << 8) + (MEMORY.readByte(address + 2) & 0xFF);
|
|
||||||
case 4:
|
|
||||||
return MEMORY.readInt(address);
|
|
||||||
case 5:
|
|
||||||
return IS_LITTLE_ENDIAN
|
|
||||||
? (MEMORY.readInt(address) & 0xFFFFFFFFL) + ((long) (MEMORY.readByte(address + 4) & 0xFF) << 32)
|
|
||||||
: ((MEMORY.readInt(address) & 0xFFFFFFFFL) << 8) + (MEMORY.readByte(address + 4) & 0xFF);
|
|
||||||
case 6:
|
|
||||||
return IS_LITTLE_ENDIAN
|
|
||||||
? (MEMORY.readInt(address) & 0xFFFFFFFFL) + ((long) (MEMORY.readShort(address + 4) & 0xFFFF) << 32)
|
|
||||||
: ((MEMORY.readInt(address) & 0xFFFFFFFFL) << 16) + (MEMORY.readShort(address + 4) & 0xFFFF);
|
|
||||||
case 7:
|
|
||||||
return IS_LITTLE_ENDIAN
|
|
||||||
? (MEMORY.readInt(address) & 0xFFFFFFFFL) + ((long) (MEMORY.readShort(address + 4) & 0xFFFF) << 32) + ((long) (MEMORY.readByte(address + 6) & 0xFF) << 48)
|
|
||||||
: ((MEMORY.readInt(address) & 0xFFFFFFFFL) << 24) + ((MEMORY.readShort(address + 4) & 0xFFFF) << 8) + (MEMORY.readByte(address + 6) & 0xFF);
|
|
||||||
default:
|
|
||||||
return len >= 8 ? MEMORY.readLong(address) : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong( BytesStore store) {
|
|
||||||
final int remaining = Maths.toInt32(store.readRemaining());
|
|
||||||
return applyAsLong(store, remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong( BytesStore store, long remaining) {
|
|
||||||
if (remaining <= 16) {
|
|
||||||
if (remaining == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (remaining < 8) {
|
|
||||||
return applyAsLong1to7(store, (int) remaining);
|
|
||||||
} else if (remaining == 8) {
|
|
||||||
return applyAsLong8(store);
|
|
||||||
} else {
|
|
||||||
return applyAsLong9to16(store, (int) remaining);
|
|
||||||
}
|
|
||||||
} else if (remaining <= 32) {
|
|
||||||
return applyAsLong17to32(store, (int) remaining);
|
|
||||||
} else if ((remaining & 31) == 0) {
|
|
||||||
return applyAsLong32bytesMultiple(store, (int) remaining);
|
|
||||||
} else {
|
|
||||||
return applyAsLongAny(store, remaining);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes.algo;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.core.Maths;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public enum VanillaBytesStoreHash implements BytesStoreHash<BytesStore> {
|
|
||||||
INSTANCE;
|
|
||||||
|
|
||||||
public static final int K0 = 0x6d0f27bd;
|
|
||||||
public static final int K1 = 0xc1f3bfc9;
|
|
||||||
public static final int K2 = 0x6b192397;
|
|
||||||
public static final int K3 = 0x6b915657;
|
|
||||||
public static final int M0 = 0x5bc80bad;
|
|
||||||
public static final int M1 = 0xea7585d7;
|
|
||||||
public static final int M2 = 0x7a646e19;
|
|
||||||
public static final int M3 = 0x855dd4db;
|
|
||||||
private static final int HI_BYTES = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN ? 4 : 0;
|
|
||||||
|
|
||||||
public static long agitate(long l) {
|
|
||||||
l ^= Long.rotateLeft(l, 26);
|
|
||||||
l ^= Long.rotateRight(l, 17);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong( BytesStore store) {
|
|
||||||
int remaining = Maths.toInt32(store.readRemaining());
|
|
||||||
return applyAsLong(store, remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong(BytesStore bytes, long length) {
|
|
||||||
long start = bytes.readPosition();
|
|
||||||
if (length <= 8) {
|
|
||||||
long l = bytes.readIncompleteLong(start);
|
|
||||||
return agitate(l * K0 + (l >> 32) * K1);
|
|
||||||
}
|
|
||||||
// use two hashes so that when they are combined the 64-bit hash is more random.
|
|
||||||
long h0 = length * K0;
|
|
||||||
long h1 = 0, h2 = 0, h3 = 0;
|
|
||||||
int i;
|
|
||||||
// optimise chunks of 32 bytes but this is the same as the next loop.
|
|
||||||
for (i = 0; i < length - 31; i += 32) {
|
|
||||||
if (i > 0) {
|
|
||||||
h0 *= K0;
|
|
||||||
h1 *= K1;
|
|
||||||
h2 *= K2;
|
|
||||||
h3 *= K3;
|
|
||||||
}
|
|
||||||
long addrI = start + i;
|
|
||||||
long l0 = bytes.readLong(addrI);
|
|
||||||
int l0a = bytes.readInt(addrI + HI_BYTES);
|
|
||||||
long l1 = bytes.readLong(addrI + 8);
|
|
||||||
int l1a = bytes.readInt(addrI + 8 + HI_BYTES);
|
|
||||||
long l2 = bytes.readLong(addrI + 16);
|
|
||||||
int l2a = bytes.readInt(addrI + 16 + HI_BYTES);
|
|
||||||
long l3 = bytes.readLong(addrI + 24);
|
|
||||||
int l3a = bytes.readInt(addrI + 24 + HI_BYTES);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform a hash of the end.
|
|
||||||
long left = length - i;
|
|
||||||
if (left > 0) {
|
|
||||||
if (i > 0) {
|
|
||||||
h0 *= K0;
|
|
||||||
h1 *= K1;
|
|
||||||
h2 *= K2;
|
|
||||||
h3 *= K3;
|
|
||||||
}
|
|
||||||
|
|
||||||
long addrI = start + i;
|
|
||||||
long l0 = bytes.readIncompleteLong(addrI);
|
|
||||||
int l0a = (int) (l0 >> 32);
|
|
||||||
long l1 = bytes.readIncompleteLong(addrI + 8);
|
|
||||||
int l1a = (int) (l1 >> 32);
|
|
||||||
long l2 = bytes.readIncompleteLong(addrI + 16);
|
|
||||||
int l2a = (int) (l2 >> 32);
|
|
||||||
long l3 = bytes.readIncompleteLong(addrI + 24);
|
|
||||||
int l3a = (int) (l3 >> 32);
|
|
||||||
|
|
||||||
h0 += (l0 + l1a - l2a) * M0;
|
|
||||||
h1 += (l1 + l2a - l3a) * M1;
|
|
||||||
h2 += (l2 + l3a - l0a) * M2;
|
|
||||||
h3 += (l3 + l0a - l1a) * M3;
|
|
||||||
}
|
|
||||||
return agitate(h0) ^ agitate(h1)
|
|
||||||
^ agitate(h2) ^ agitate(h3);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.algo;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
|
|
||||||
// Migration of XxHash from Zero-Allocation-Hashing
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class XxHash implements BytesStoreHash<BytesStore> {
|
|
||||||
// Primes if treated as unsigned
|
|
||||||
private static final long P1 = -7046029288634856825L;
|
|
||||||
private static final long P2 = -4417276706812531889L;
|
|
||||||
private static final long P3 = 1609587929392839161L;
|
|
||||||
private static final long P4 = -8796714831421723037L;
|
|
||||||
public static final XxHash INSTANCE = new XxHash(P4);
|
|
||||||
private static final long P5 = 2870177450012600261L;
|
|
||||||
private final long seed;
|
|
||||||
|
|
||||||
public XxHash(long seed) {
|
|
||||||
this.seed = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long finalize(long hash) {
|
|
||||||
hash ^= hash >>> 33;
|
|
||||||
hash *= P2;
|
|
||||||
hash ^= hash >>> 29;
|
|
||||||
hash *= P3;
|
|
||||||
hash ^= hash >>> 32;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
long fetch64(BytesStore bytes, long off) {
|
|
||||||
return bytes.readLong(off);
|
|
||||||
}
|
|
||||||
|
|
||||||
// long because of unsigned nature of original algorithm
|
|
||||||
long fetch32(BytesStore bytes, long off) {
|
|
||||||
return bytes.readUnsignedInt(off);
|
|
||||||
}
|
|
||||||
|
|
||||||
// int because of unsigned nature of original algorithm
|
|
||||||
long fetch8(BytesStore bytes, long off) {
|
|
||||||
return bytes.readUnsignedByte(off);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong(BytesStore bytes) {
|
|
||||||
return applyAsLong(bytes, bytes.readRemaining());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long applyAsLong(BytesStore bytes, long length) {
|
|
||||||
long hash;
|
|
||||||
long remaining = length;
|
|
||||||
long off = bytes.readPosition();
|
|
||||||
|
|
||||||
if (remaining >= 32) {
|
|
||||||
long v1 = seed + P1 + P2;
|
|
||||||
long v2 = seed + P2;
|
|
||||||
long v3 = seed;
|
|
||||||
long v4 = seed - P1;
|
|
||||||
|
|
||||||
do {
|
|
||||||
v1 += fetch64(bytes, off) * P2;
|
|
||||||
v1 = Long.rotateLeft(v1, 31);
|
|
||||||
v1 *= P1;
|
|
||||||
|
|
||||||
v2 += fetch64(bytes, off + 8) * P2;
|
|
||||||
v2 = Long.rotateLeft(v2, 31);
|
|
||||||
v2 *= P1;
|
|
||||||
|
|
||||||
v3 += fetch64(bytes, off + 16) * P2;
|
|
||||||
v3 = Long.rotateLeft(v3, 31);
|
|
||||||
v3 *= P1;
|
|
||||||
|
|
||||||
v4 += fetch64(bytes, off + 24) * P2;
|
|
||||||
v4 = Long.rotateLeft(v4, 31);
|
|
||||||
v4 *= P1;
|
|
||||||
|
|
||||||
off += 32;
|
|
||||||
remaining -= 32;
|
|
||||||
} while (remaining >= 32);
|
|
||||||
|
|
||||||
hash = Long.rotateLeft(v1, 1)
|
|
||||||
+ Long.rotateLeft(v2, 7)
|
|
||||||
+ Long.rotateLeft(v3, 12)
|
|
||||||
+ Long.rotateLeft(v4, 18);
|
|
||||||
|
|
||||||
v1 *= P2;
|
|
||||||
v1 = Long.rotateLeft(v1, 31);
|
|
||||||
v1 *= P1;
|
|
||||||
hash ^= v1;
|
|
||||||
hash = hash * P1 + P4;
|
|
||||||
|
|
||||||
v2 *= P2;
|
|
||||||
v2 = Long.rotateLeft(v2, 31);
|
|
||||||
v2 *= P1;
|
|
||||||
hash ^= v2;
|
|
||||||
hash = hash * P1 + P4;
|
|
||||||
|
|
||||||
v3 *= P2;
|
|
||||||
v3 = Long.rotateLeft(v3, 31);
|
|
||||||
v3 *= P1;
|
|
||||||
hash ^= v3;
|
|
||||||
hash = hash * P1 + P4;
|
|
||||||
|
|
||||||
v4 *= P2;
|
|
||||||
v4 = Long.rotateLeft(v4, 31);
|
|
||||||
v4 *= P1;
|
|
||||||
hash ^= v4;
|
|
||||||
hash = hash * P1 + P4;
|
|
||||||
} else {
|
|
||||||
hash = seed + P5;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash += length;
|
|
||||||
|
|
||||||
while (remaining >= 8) {
|
|
||||||
long k1 = fetch64(bytes, off);
|
|
||||||
k1 *= P2;
|
|
||||||
k1 = Long.rotateLeft(k1, 31);
|
|
||||||
k1 *= P1;
|
|
||||||
hash ^= k1;
|
|
||||||
hash = Long.rotateLeft(hash, 27) * P1 + P4;
|
|
||||||
off += 8;
|
|
||||||
remaining -= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining >= 4) {
|
|
||||||
hash ^= fetch32(bytes, off) * P1;
|
|
||||||
hash = Long.rotateLeft(hash, 23) * P2 + P3;
|
|
||||||
off += 4;
|
|
||||||
remaining -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (remaining != 0) {
|
|
||||||
hash ^= fetch8(bytes, off) * P5;
|
|
||||||
hash = Long.rotateLeft(hash, 11) * P1;
|
|
||||||
--remaining;
|
|
||||||
++off;
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalize(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
* This package and any and all sub-packages contains strictly internal classes for this Chronicle library.
|
|
||||||
* Internal classes shall <em>never</em> be used directly.
|
|
||||||
* <p>
|
|
||||||
* Specifically, the following actions (including, but not limited to) are not allowed
|
|
||||||
* on internal classes and packages:
|
|
||||||
* <ul>
|
|
||||||
* <li>Casting to</li>
|
|
||||||
* <li>Reflection of any kind</li>
|
|
||||||
* <li>Explicit Serialize/deserialize</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* The classes in this package and any sub-package are subject to
|
|
||||||
* changes at any time for any reason.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.internal;
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.openhft.chronicle.bytes.pool;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.Bytes;
|
|
||||||
import net.openhft.chronicle.core.io.IOTools;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BytesPool {
|
|
||||||
final ThreadLocal<Bytes> bytesTL = new ThreadLocal<>();
|
|
||||||
|
|
||||||
public Bytes acquireBytes() {
|
|
||||||
Bytes bytes = bytesTL.get();
|
|
||||||
if (bytes == null) {
|
|
||||||
bytesTL.set(bytes = createBytes());
|
|
||||||
} else {
|
|
||||||
bytes.clear();
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Bytes createBytes() {
|
|
||||||
// use heap buffer as we never know when a thread will die and not release this resource.
|
|
||||||
Bytes<ByteBuffer> bbb = Bytes.elasticHeapByteBuffer(256);
|
|
||||||
IOTools.unmonitor(bbb);
|
|
||||||
return bbb;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.Byteable;
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.core.io.AbstractCloseable;
|
|
||||||
import net.openhft.chronicle.core.io.Closeable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public abstract class AbstractReference extends AbstractCloseable implements Byteable, Closeable {
|
|
||||||
|
|
||||||
|
|
||||||
protected BytesStore<?, ?> bytes;
|
|
||||||
protected long offset;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bytesStore( final BytesStore bytes, final long offset, final long length) throws IllegalStateException, IllegalArgumentException, BufferOverflowException, BufferUnderflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
acceptNewBytesStore(bytes);
|
|
||||||
this.offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore bytesStore() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long offset() {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract long maxSize();
|
|
||||||
|
|
||||||
protected void acceptNewBytesStore( final BytesStore bytes) {
|
|
||||||
if (this.bytes != null) {
|
|
||||||
this.bytes.release(this);
|
|
||||||
}
|
|
||||||
this.bytes = bytes.bytesStore();
|
|
||||||
this.bytes.reserve(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void performClose() {
|
|
||||||
if (this.bytes != null) {
|
|
||||||
this.bytes.release(this);
|
|
||||||
this.bytes = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long address() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytesStore().addressForRead(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO FIX
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
warnIfNotClosed();
|
|
||||||
super.finalize();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean threadSafetyCheck(boolean isUsed) {
|
|
||||||
// References are thread safe
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.core.values.BooleanValue;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
public class BinaryBooleanReference extends AbstractReference implements BooleanValue {
|
|
||||||
|
|
||||||
private static final byte FALSE = (byte) 0xB0;
|
|
||||||
private static final byte TRUE = (byte) 0xB1;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public void bytesStore( final BytesStore bytes, final long offset, final long length) throws IllegalStateException, IllegalArgumentException, BufferOverflowException, BufferUnderflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
if (length != maxSize())
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
|
|
||||||
super.bytesStore(bytes, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getValue() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
byte b = bytes.readByte(offset);
|
|
||||||
if (b == FALSE)
|
|
||||||
return false;
|
|
||||||
if (b == TRUE)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
throw new IllegalStateException("unexpected code=" + b);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(final boolean flag) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
bytes.writeByte(offset, flag ? TRUE : FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,282 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.*;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.values.IntValue;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.IdentityHashMap;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.ref.BinaryIntReference.INT_NOT_COMPLETE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class acts a Binary array of 64-bit values. c.f. TextLongArrayReference
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BinaryIntArrayReference extends AbstractReference implements ByteableIntArrayValues, BytesMarshallable {
|
|
||||||
public static final int SHIFT = 2;
|
|
||||||
private static final long CAPACITY = 0;
|
|
||||||
private static final long USED = CAPACITY + Long.BYTES;
|
|
||||||
private static final long VALUES = USED + Long.BYTES;
|
|
||||||
private static final int MAX_TO_STRING = 1024;
|
|
||||||
|
|
||||||
private static Set<WeakReference<BinaryIntArrayReference>> binaryIntArrayReferences = null;
|
|
||||||
private long length;
|
|
||||||
|
|
||||||
public BinaryIntArrayReference() {
|
|
||||||
this(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BinaryIntArrayReference(long defaultCapacity) {
|
|
||||||
this.length = (defaultCapacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startCollecting() {
|
|
||||||
binaryIntArrayReferences = Collections.newSetFromMap(new IdentityHashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forceAllToNotCompleteState() {
|
|
||||||
binaryIntArrayReferences.forEach(x -> {
|
|
||||||
BinaryIntArrayReference binaryLongReference = x.get();
|
|
||||||
if (binaryLongReference != null) {
|
|
||||||
binaryLongReference.setValueAt(0, INT_NOT_COMPLETE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
binaryIntArrayReferences = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void write( Bytes bytes, long capacity) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
assert (bytes.writePosition() & 0x7) == 0;
|
|
||||||
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0L); // used
|
|
||||||
long start = bytes.writePosition();
|
|
||||||
bytes.zeroOut(start, start + (capacity << SHIFT));
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void lazyWrite( Bytes bytes, long capacity) throws BufferOverflowException {
|
|
||||||
assert (bytes.writePosition() & 0x7) == 0;
|
|
||||||
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0L); // used
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long peakLength( BytesStore bytes, long offset) throws BufferUnderflowException {
|
|
||||||
final long capacity = bytes.readLong(offset + CAPACITY);
|
|
||||||
assert capacity > 0 : "capacity too small " + capacity;
|
|
||||||
return (capacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getCapacity() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return (length - VALUES) >>> SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUsed() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readVolatileInt(offset + USED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMaxUsed(long usedAtLeast) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeMaxLong(offset + USED, usedAtLeast);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getValueAt(long index) throws BufferUnderflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readInt(VALUES + offset + (index << SHIFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValueAt(long index, int value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeInt(VALUES + offset + (index << SHIFT), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVolatileValueAt(long index) throws BufferUnderflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readVolatileInt(VALUES + offset + (index << SHIFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindValueAt(long index, IntValue value) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
((BinaryIntReference) value).bytesStore(bytes, VALUES + offset + (index << SHIFT), 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOrderedValueAt(long index, int value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeOrderedInt(VALUES + offset + (index << SHIFT), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bytesStore( BytesStore bytes, long offset, long length) throws BufferUnderflowException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (length != peakLength(bytes, offset))
|
|
||||||
throw new IllegalArgumentException(length + " != " + peakLength(bytes, offset));
|
|
||||||
|
|
||||||
assert (offset & 7) == 0 : "offset=" + offset;
|
|
||||||
super.bytesStore(bytes, (offset + 7) & ~7, length);
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readMarshallable(BytesIn bytes) throws IORuntimeException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
long position = bytes.readPosition();
|
|
||||||
long capacity = bytes.readLong();
|
|
||||||
long used = bytes.readLong();
|
|
||||||
if (capacity < 0 || capacity > bytes.readRemaining() >> SHIFT)
|
|
||||||
throw new IORuntimeException("Corrupt used capacity");
|
|
||||||
|
|
||||||
if (used < 0 || used > capacity)
|
|
||||||
throw new IORuntimeException("Corrupt used value");
|
|
||||||
|
|
||||||
bytes.readSkip(capacity << SHIFT);
|
|
||||||
long length = bytes.readPosition() - position;
|
|
||||||
bytesStore(((Bytes) bytes).bytesStore(), position, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeMarshallable(BytesOut bytes) {
|
|
||||||
BytesStore bytesStore = bytesStore();
|
|
||||||
if (bytesStore == null) {
|
|
||||||
long capacity = getCapacity();
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0);
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
} else {
|
|
||||||
bytes.write(bytesStore, offset, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNull() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes = null;
|
|
||||||
offset = 0;
|
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore bytesStore() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long offset() {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
if (bytes == null)
|
|
||||||
return "not set";
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("used: ");
|
|
||||||
long used = getUsed();
|
|
||||||
sb.append(used);
|
|
||||||
sb.append(", value: ");
|
|
||||||
String sep = "";
|
|
||||||
try {
|
|
||||||
int i, max = (int) Math.min(used, Math.min(getCapacity(), MAX_TO_STRING));
|
|
||||||
for (i = 0; i < max; i++) {
|
|
||||||
long valueAt = getValueAt(i);
|
|
||||||
sb.append(sep).append(valueAt);
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
if (i < getCapacity())
|
|
||||||
sb.append(" ...");
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
sb.append(" ").append(e);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long sizeInBytes(long capacity) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return (capacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteableIntArrayValues capacity(long arrayLength) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
BytesStore bytesStore = bytesStore();
|
|
||||||
long length = sizeInBytes(arrayLength);
|
|
||||||
if (bytesStore == null) {
|
|
||||||
this.length = length;
|
|
||||||
} else {
|
|
||||||
assert this.length == length;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSet(long index, int expected, int value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (value == INT_NOT_COMPLETE && binaryIntArrayReferences != null)
|
|
||||||
binaryIntArrayReferences.add(new WeakReference<>(this));
|
|
||||||
return bytes.compareAndSwapInt(VALUES + offset + (index << SHIFT), expected, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import net.openhft.chronicle.core.values.IntValue;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class acts as a Binary 32-bit in values. c.f. TextIntReference
|
|
||||||
*/
|
|
||||||
public class BinaryIntReference extends AbstractReference implements IntValue {
|
|
||||||
public static final int INT_NOT_COMPLETE = Integer.MIN_VALUE;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public void bytesStore( final BytesStore bytes, final long offset, final long length) throws IllegalStateException, IllegalArgumentException, BufferOverflowException, BufferUnderflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
if (length != maxSize())
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
super.bytesStore(bytes, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return bytes == null ? "bytes is null" : "value: " + getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getValue() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes == null ? 0 : bytes.readInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(int value) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeInt(offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVolatileValue() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readVolatileInt(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOrderedValue(int value) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeOrderedInt(offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int addValue(int delta) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.addAndGetInt(offset, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int addAtomicValue(int delta) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return addValue(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapValue(int expected, int value) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.compareAndSwapInt(offset, expected, value);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,282 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.*;
|
|
||||||
import net.openhft.chronicle.core.io.IORuntimeException;
|
|
||||||
import net.openhft.chronicle.core.values.LongValue;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.IdentityHashMap;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static net.openhft.chronicle.bytes.ref.BinaryLongReference.LONG_NOT_COMPLETE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class acts a Binary array of 64-bit values. c.f. TextLongArrayReference
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class BinaryLongArrayReference extends AbstractReference implements ByteableLongArrayValues, BytesMarshallable {
|
|
||||||
public static final int SHIFT = 3;
|
|
||||||
private static final long CAPACITY = 0;
|
|
||||||
private static final long USED = CAPACITY + Long.BYTES;
|
|
||||||
private static final long VALUES = USED + Long.BYTES;
|
|
||||||
private static final int MAX_TO_STRING = 1024;
|
|
||||||
|
|
||||||
private static Set<WeakReference<BinaryLongArrayReference>> binaryLongArrayReferences = null;
|
|
||||||
private long length;
|
|
||||||
|
|
||||||
public BinaryLongArrayReference() {
|
|
||||||
this(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BinaryLongArrayReference(long defaultCapacity) {
|
|
||||||
this.length = (defaultCapacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startCollecting() {
|
|
||||||
binaryLongArrayReferences = Collections.newSetFromMap(new IdentityHashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forceAllToNotCompleteState() {
|
|
||||||
binaryLongArrayReferences.forEach(x -> {
|
|
||||||
BinaryLongArrayReference binaryLongReference = x.get();
|
|
||||||
if (binaryLongReference != null) {
|
|
||||||
binaryLongReference.setValueAt(0, LONG_NOT_COMPLETE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
binaryLongArrayReferences = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void write( Bytes bytes, long capacity) throws BufferOverflowException, IllegalArgumentException {
|
|
||||||
assert (bytes.writePosition() & 0x7) == 0;
|
|
||||||
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0L); // used
|
|
||||||
long start = bytes.writePosition();
|
|
||||||
bytes.zeroOut(start, start + (capacity << SHIFT));
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void lazyWrite( Bytes bytes, long capacity) throws BufferOverflowException {
|
|
||||||
assert (bytes.writePosition() & 0x7) == 0;
|
|
||||||
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0L); // used
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long peakLength( BytesStore bytes, long offset) throws BufferUnderflowException {
|
|
||||||
final long capacity = bytes.readLong(offset + CAPACITY);
|
|
||||||
assert capacity > 0 : "capacity too small " + capacity;
|
|
||||||
return (capacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getCapacity() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return (length - VALUES) >>> SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUsed() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readVolatileLong(offset + USED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMaxUsed(long usedAtLeast) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeMaxLong(offset + USED, usedAtLeast);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValueAt(long index) throws BufferUnderflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readLong(VALUES + offset + (index << SHIFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValueAt(long index, long value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeLong(VALUES + offset + (index << SHIFT), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getVolatileValueAt(long index) throws BufferUnderflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes.readVolatileLong(VALUES + offset + (index << SHIFT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindValueAt(long index, LongValue value) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
((BinaryLongReference) value).bytesStore(bytes, VALUES + offset + (index << SHIFT), 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOrderedValueAt(long index, long value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes.writeOrderedLong(VALUES + offset + (index << SHIFT), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bytesStore( BytesStore bytes, long offset, long length) throws BufferUnderflowException, IllegalArgumentException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (length != peakLength(bytes, offset))
|
|
||||||
throw new IllegalArgumentException(length + " != " + peakLength(bytes, offset));
|
|
||||||
|
|
||||||
assert (offset & 7) == 0 : "offset=" + offset;
|
|
||||||
super.bytesStore(bytes, (offset + 7) & ~7, length);
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readMarshallable(BytesIn bytes) throws IORuntimeException {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
long position = bytes.readPosition();
|
|
||||||
long capacity = bytes.readLong();
|
|
||||||
long used = bytes.readLong();
|
|
||||||
if (capacity < 0 || capacity > bytes.readRemaining() >> SHIFT)
|
|
||||||
throw new IORuntimeException("Corrupt used capacity");
|
|
||||||
|
|
||||||
if (used < 0 || used > capacity)
|
|
||||||
throw new IORuntimeException("Corrupt used value");
|
|
||||||
|
|
||||||
bytes.readSkip(capacity << SHIFT);
|
|
||||||
long length = bytes.readPosition() - position;
|
|
||||||
bytesStore(((Bytes) bytes).bytesStore(), position, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeMarshallable(BytesOut bytes) {
|
|
||||||
BytesStore bytesStore = bytesStore();
|
|
||||||
if (bytesStore == null) {
|
|
||||||
long capacity = getCapacity();
|
|
||||||
bytes.writeLong(capacity);
|
|
||||||
bytes.writeLong(0);
|
|
||||||
bytes.writeSkip(capacity << SHIFT);
|
|
||||||
} else {
|
|
||||||
bytes.write(bytesStore, offset, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNull() {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return bytes == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
bytes = null;
|
|
||||||
offset = 0;
|
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BytesStore bytesStore() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long offset() {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
if (bytes == null)
|
|
||||||
return "not set";
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("used: ");
|
|
||||||
long used = getUsed();
|
|
||||||
sb.append(used);
|
|
||||||
sb.append(", value: ");
|
|
||||||
String sep = "";
|
|
||||||
try {
|
|
||||||
int i, max = (int) Math.min(used, Math.min(getCapacity(), MAX_TO_STRING));
|
|
||||||
for (i = 0; i < max; i++) {
|
|
||||||
long valueAt = getValueAt(i);
|
|
||||||
sb.append(sep).append(valueAt);
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
if (i < getCapacity())
|
|
||||||
sb.append(" ...");
|
|
||||||
|
|
||||||
} catch (BufferUnderflowException e) {
|
|
||||||
sb.append(" ").append(e);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long sizeInBytes(long capacity) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
return (capacity << SHIFT) + VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteableLongArrayValues capacity(long arrayLength) {
|
|
||||||
throwExceptionIfClosedInSetter();
|
|
||||||
|
|
||||||
BytesStore bytesStore = bytesStore();
|
|
||||||
long length = sizeInBytes(arrayLength);
|
|
||||||
if (bytesStore == null) {
|
|
||||||
this.length = length;
|
|
||||||
} else {
|
|
||||||
assert this.length == length;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSet(long index, long expected, long value) throws IllegalArgumentException, BufferOverflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (value == LONG_NOT_COMPLETE && binaryLongArrayReferences != null)
|
|
||||||
binaryLongArrayReferences.add(new WeakReference<>(this));
|
|
||||||
return bytes.compareAndSwapLong(VALUES + offset + (index << SHIFT), expected, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,136 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import net.openhft.chronicle.bytes.BytesStore;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.nio.BufferOverflowException;
|
|
||||||
import java.nio.BufferUnderflowException;
|
|
||||||
|
|
||||||
public class BinaryLongReference extends AbstractReference implements LongReference {
|
|
||||||
public static final long LONG_NOT_COMPLETE = -1;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public void bytesStore( final BytesStore bytes, final long offset, final long length) throws IllegalStateException, IllegalArgumentException, BufferOverflowException, BufferUnderflowException {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
if (length != maxSize())
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
|
|
||||||
super.bytesStore(bytes, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return bytes == null ? "bytes is null" : "value: " + getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue() {
|
|
||||||
return bytes == null ? 0L : bytes.readLong(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeLong(offset, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getVolatileValue() {
|
|
||||||
try {
|
|
||||||
return bytes.readVolatileLong(offset);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVolatileValue(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeVolatileLong(offset, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getVolatileValue(long closedValue) {
|
|
||||||
if (isClosed())
|
|
||||||
return closedValue;
|
|
||||||
try {
|
|
||||||
return getVolatileValue();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return closedValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOrderedValue(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeOrderedLong(offset, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addValue(long delta) {
|
|
||||||
try {
|
|
||||||
return bytes.addAndGetLong(offset, delta);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addAtomicValue(long delta) {
|
|
||||||
return addValue(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapValue(long expected, long value) {
|
|
||||||
try {
|
|
||||||
return bytes.compareAndSwapLong(offset, expected, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2016-2020 chronicle.software
|
|
||||||
*
|
|
||||||
* https://chronicle.software
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package net.openhft.chronicle.bytes.ref;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class BinaryTwoLongReference extends BinaryLongReference implements TwoLongReference {
|
|
||||||
@Override
|
|
||||||
public long maxSize() {
|
|
||||||
return 2 * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return bytes == null ? "bytes is null" : "value: " + getValue() + ", value2: " + getValue2();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getValue2() {
|
|
||||||
try {
|
|
||||||
return bytes.readLong(offset + 8);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue2(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeLong(offset + 8, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getVolatileValue2() {
|
|
||||||
try {
|
|
||||||
return bytes.readVolatileLong(offset + 8);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVolatileValue2(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeVolatileLong(offset + 8, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setOrderedValue2(long value) {
|
|
||||||
try {
|
|
||||||
bytes.writeOrderedLong(offset + 8, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addValue2(long delta) {
|
|
||||||
try {
|
|
||||||
return bytes.addAndGetLong(offset + 8, delta);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long addAtomicValue2(long delta) {
|
|
||||||
try {
|
|
||||||
return addValue2(delta);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean compareAndSwapValue2(long expected, long value) {
|
|
||||||
try {
|
|
||||||
return bytes.compareAndSwapLong(offset + 8, expected, value);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throwExceptionIfClosed();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue