blob: 9092cd901536d9a14f3d5088d826fd5f17e2ac90 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
namespace Apache.Ignite.Core.Impl.Binary.IO
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using Apache.Ignite.Core.Impl.Memory;
/// <summary>
/// Binary onheap stream.
/// </summary>
internal unsafe class BinaryHeapStream : IBinaryStream
{
/** Byte: zero. */
private const byte ByteZero = 0;
/** Byte: one. */
private const byte ByteOne = 1;
/** LITTLE_ENDIAN flag. */
private static readonly bool LittleEndian = BitConverter.IsLittleEndian;
/** Position. */
private int _pos;
/** Data array. */
private byte[] _data;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="cap">Initial capacity.</param>
public BinaryHeapStream(int cap)
{
Debug.Assert(cap >= 0);
_data = new byte[cap];
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="data">Data array.</param>
public BinaryHeapStream(byte[] data)
{
Debug.Assert(data != null);
_data = data;
}
/// <summary>
/// Internal routine to write byte array.
/// </summary>
/// <param name="val">Byte array.</param>
/// <param name="data">Data pointer.</param>
private static void WriteByteArray0(byte[] val, byte* data)
{
fixed (byte* val0 = val)
{
CopyMemory(val0, data, val.Length);
}
}
/// <summary>
/// Internal routine to read byte array.
/// </summary>
/// <param name="len">Array length.</param>
/// <param name="data">Data pointer.</param>
/// <returns>Byte array</returns>
private static byte[] ReadByteArray0(int len, byte* data)
{
byte[] res = new byte[len];
fixed (byte* res0 = res)
{
CopyMemory(data, res0, len);
}
return res;
}
/** <inheritdoc /> */
public void WriteBool(bool val)
{
WriteByte(val ? ByteOne : ByteZero);
}
/** <inheritdoc /> */
public bool ReadBool()
{
return ReadByte() == ByteOne;
}
/// <summary>
/// Internal routine to write bool array.
/// </summary>
/// <param name="val">Bool array.</param>
/// <param name="data">Data pointer.</param>
private static void WriteBoolArray0(bool[] val, byte* data)
{
fixed (bool* val0 = val)
{
CopyMemory((byte*)val0, data, val.Length);
}
}
/// <summary>
/// Internal routine to read bool array.
/// </summary>
/// <param name="len">Array length.</param>
/// <param name="data">Data pointer.</param>
/// <returns>Bool array</returns>
private static bool[] ReadBoolArray0(int len, byte* data)
{
bool[] res = new bool[len];
fixed (bool* res0 = res)
{
CopyMemory(data, (byte*)res0, len);
}
return res;
}
/// <summary>
/// Internal routine to write short value.
/// </summary>
/// <param name="val">Short value.</param>
/// <param name="data">Data pointer.</param>
private static void WriteShort0(short val, byte* data)
{
if (LittleEndian)
*((short*)data) = val;
else
{
byte* valPtr = (byte*)&val;
data[0] = valPtr[1];
data[1] = valPtr[0];
}
}
/// <summary>
/// Internal routine to read short value.
/// </summary>
/// <param name="data">Data pointer.</param>
/// <returns>Short value</returns>
private static short ReadShort0(byte* data)
{
short val;
if (LittleEndian)
val = *((short*)data);
else
{
byte* valPtr = (byte*)&val;
valPtr[0] = data[1];
valPtr[1] = data[0];
}
return val;
}
/// <summary>
/// Internal routine to write short array.
/// </summary>
/// <param name="val">Short array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteShortArray0(short[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (short* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
short val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read short array.
/// </summary>
/// <param name="len">Array length.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Short array</returns>
private static short[] ReadShortArray0(int len, byte* data, int cnt)
{
short[] res = new short[len];
if (LittleEndian)
{
fixed (short* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
short val;
byte* valPtr = (byte*)&val;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/** <inheritdoc /> */
public void WriteChar(char val)
{
WriteShort(*(short*)(&val));
}
/** <inheritdoc /> */
public char ReadChar()
{
short val = ReadShort();
return *(char*)(&val);
}
/// <summary>
/// Internal routine to write char array.
/// </summary>
/// <param name="val">Char array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteCharArray0(char[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (char* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
char val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read char array.
/// </summary>
/// <param name="len">Count.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Char array</returns>
private static char[] ReadCharArray0(int len, byte* data, int cnt)
{
char[] res = new char[len];
if (LittleEndian)
{
fixed (char* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
char val;
byte* valPtr = (byte*)&val;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/// <summary>
/// Internal routine to write int value.
/// </summary>
/// <param name="val">Int value.</param>
/// <param name="data">Data pointer.</param>
private static void WriteInt0(int val, byte* data)
{
if (LittleEndian)
*((int*)data) = val;
else
{
byte* valPtr = (byte*)&val;
data[0] = valPtr[3];
data[1] = valPtr[2];
data[2] = valPtr[1];
data[3] = valPtr[0];
}
}
/// <summary>
/// Internal routine to read int value.
/// </summary>
/// <param name="data">Data pointer.</param>
/// <returns>Int value</returns>
public static int ReadInt0(byte* data) {
int val;
if (LittleEndian)
val = *((int*)data);
else
{
byte* valPtr = (byte*)&val;
valPtr[0] = data[3];
valPtr[1] = data[2];
valPtr[2] = data[1];
valPtr[3] = data[0];
}
return val;
}
/// <summary>
/// Internal routine to write int array.
/// </summary>
/// <param name="val">Int array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteIntArray0(int[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (int* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
int val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[3];
*curPos++ = valPtr[2];
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read int array.
/// </summary>
/// <param name="len">Count.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Int array</returns>
private static int[] ReadIntArray0(int len, byte* data, int cnt)
{
int[] res = new int[len];
if (LittleEndian)
{
fixed (int* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
int val;
byte* valPtr = (byte*)&val;
valPtr[3] = *data++;
valPtr[2] = *data++;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/** <inheritdoc /> */
public void WriteFloat(float val)
{
int val0 = *(int*)(&val);
WriteInt(val0);
}
/** <inheritdoc /> */
public float ReadFloat()
{
int val = ReadInt();
return BinaryUtils.IntToFloatBits(val);
}
/// <summary>
/// Internal routine to write float array.
/// </summary>
/// <param name="val">Int array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteFloatArray0(float[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (float* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
float val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[3];
*curPos++ = valPtr[2];
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read float array.
/// </summary>
/// <param name="len">Count.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Float array</returns>
private static float[] ReadFloatArray0(int len, byte* data, int cnt)
{
float[] res = new float[len];
if (LittleEndian)
{
fixed (float* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
int val;
byte* valPtr = (byte*)&val;
valPtr[3] = *data++;
valPtr[2] = *data++;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/// <summary>
/// Internal routine to write long value.
/// </summary>
/// <param name="val">Long value.</param>
/// <param name="data">Data pointer.</param>
private static void WriteLong0(long val, byte* data)
{
if (LittleEndian)
*((long*)data) = val;
else
{
byte* valPtr = (byte*)&val;
data[0] = valPtr[7];
data[1] = valPtr[6];
data[2] = valPtr[5];
data[3] = valPtr[4];
data[4] = valPtr[3];
data[5] = valPtr[2];
data[6] = valPtr[1];
data[7] = valPtr[0];
}
}
/// <summary>
/// Internal routine to read long value.
/// </summary>
/// <param name="data">Data pointer.</param>
/// <returns>Long value</returns>
private static long ReadLong0(byte* data)
{
long val;
if (LittleEndian)
val = *((long*)data);
else
{
byte* valPtr = (byte*)&val;
valPtr[0] = data[7];
valPtr[1] = data[6];
valPtr[2] = data[5];
valPtr[3] = data[4];
valPtr[4] = data[3];
valPtr[5] = data[2];
valPtr[6] = data[1];
valPtr[7] = data[0];
}
return val;
}
/// <summary>
/// Internal routine to write long array.
/// </summary>
/// <param name="val">Long array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteLongArray0(long[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (long* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
long val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[7];
*curPos++ = valPtr[6];
*curPos++ = valPtr[5];
*curPos++ = valPtr[4];
*curPos++ = valPtr[3];
*curPos++ = valPtr[2];
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read long array.
/// </summary>
/// <param name="len">Count.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Long array</returns>
private static long[] ReadLongArray0(int len, byte* data, int cnt)
{
long[] res = new long[len];
if (LittleEndian)
{
fixed (long* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
long val;
byte* valPtr = (byte*)&val;
valPtr[7] = *data++;
valPtr[6] = *data++;
valPtr[5] = *data++;
valPtr[4] = *data++;
valPtr[3] = *data++;
valPtr[2] = *data++;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/** <inheritdoc /> */
public void WriteDouble(double val)
{
long val0 = *(long*)(&val);
WriteLong(val0);
}
/** <inheritdoc /> */
public double ReadDouble()
{
long val = ReadLong();
return BinaryUtils.LongToDoubleBits(val);
}
/// <summary>
/// Internal routine to write double array.
/// </summary>
/// <param name="val">Double array.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
private static void WriteDoubleArray0(double[] val, byte* data, int cnt)
{
if (LittleEndian)
{
fixed (double* val0 = val)
{
CopyMemory((byte*)val0, data, cnt);
}
}
else
{
byte* curPos = data;
for (int i = 0; i < val.Length; i++)
{
double val0 = val[i];
byte* valPtr = (byte*)&(val0);
*curPos++ = valPtr[7];
*curPos++ = valPtr[6];
*curPos++ = valPtr[5];
*curPos++ = valPtr[4];
*curPos++ = valPtr[3];
*curPos++ = valPtr[2];
*curPos++ = valPtr[1];
*curPos++ = valPtr[0];
}
}
}
/// <summary>
/// Internal routine to read double array.
/// </summary>
/// <param name="len">Count.</param>
/// <param name="data">Data pointer.</param>
/// <param name="cnt">Bytes count.</param>
/// <returns>Double array</returns>
private static double[] ReadDoubleArray0(int len, byte* data, int cnt)
{
double[] res = new double[len];
if (LittleEndian)
{
fixed (double* res0 = res)
{
CopyMemory(data, (byte*)res0, cnt);
}
}
else
{
for (int i = 0; i < len; i++)
{
double val;
byte* valPtr = (byte*)&val;
valPtr[7] = *data++;
valPtr[6] = *data++;
valPtr[5] = *data++;
valPtr[4] = *data++;
valPtr[3] = *data++;
valPtr[2] = *data++;
valPtr[1] = *data++;
valPtr[0] = *data++;
res[i] = val;
}
}
return res;
}
/** <inheritdoc /> */
public void Write(byte[] src, int off, int cnt)
{
fixed (byte* src0 = src)
{
Write(src0 + off, cnt);
}
}
/** <inheritdoc /> */
public void Read(byte[] dest, int off, int cnt)
{
fixed (byte* dest0 = dest)
{
Read(dest0 + off, cnt);
}
}
/// <summary>
/// Internal write routine.
/// </summary>
/// <param name="src">Source.</param>
/// <param name="cnt">Count.</param>
/// <param name="data">Data (dsetination).</param>
private void WriteInternal(byte* src, int cnt, byte* data)
{
CopyMemory(src, data + _pos, cnt);
}
/// <summary>
/// Internal read routine.
/// </summary>
/// <param name="src">Source</param>
/// <param name="dest">Destination.</param>
/// <param name="cnt">Count.</param>
/// <returns>Amount of bytes written.</returns>
private void ReadInternal(byte* src, byte* dest, int cnt)
{
int cnt0 = Math.Min(Remaining, cnt);
CopyMemory(src + _pos, dest, cnt0);
ShiftRead(cnt0);
}
/** <inheritdoc /> */
public int Position
{
get { return _pos; }
}
/** <inheritdoc /> */
public int Remaining
{
get { return _data.Length - _pos; }
}
/// <summary>
/// Internal array.
/// </summary>
internal byte[] InternalArray
{
get { return _data; }
}
/// <inheritdoc />
/// <exception cref="System.ArgumentException">
/// Unsupported seek origin: + origin
/// or
/// Seek before origin: + newPos
/// </exception>
public int Seek(int offset, SeekOrigin origin)
{
int newPos;
switch (origin)
{
case SeekOrigin.Begin:
{
newPos = offset;
break;
}
case SeekOrigin.Current:
{
newPos = _pos + offset;
break;
}
default:
throw new ArgumentException("Unsupported seek origin: " + origin);
}
if (newPos < 0)
throw new ArgumentException("Seek before origin: " + newPos);
EnsureWriteCapacity(newPos);
_pos = newPos;
return _pos;
}
/** <inheritdoc /> */
public void Flush()
{
// No-op.
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
Justification = "There is no finalizer.")]
public void Dispose()
{
// No-op.
}
/// <summary>
/// Ensure capacity for write and shift position.
/// </summary>
/// <param name="cnt">Bytes count.</param>
/// <returns>Position before shift.</returns>
private int EnsureWriteCapacityAndShift(int cnt)
{
int pos0 = _pos;
EnsureWriteCapacity(_pos + cnt);
ShiftWrite(cnt);
return pos0;
}
/// <summary>
/// Ensure capacity for read and shift position.
/// </summary>
/// <param name="cnt">Bytes count.</param>
/// <returns>Position before shift.</returns>
private int EnsureReadCapacityAndShift(int cnt)
{
int pos0 = _pos;
EnsureReadCapacity(cnt);
ShiftRead(cnt);
return pos0;
}
/// <summary>
/// Shift position due to write
/// </summary>
/// <param name="cnt">Bytes count.</param>
private void ShiftWrite(int cnt)
{
_pos += cnt;
}
/// <summary>
/// Shift position due to read.
/// </summary>
/// <param name="cnt">Bytes count.</param>
private void ShiftRead(int cnt)
{
_pos += cnt;
}
/// <summary>
/// Calculate new capacity.
/// </summary>
/// <param name="curCap">Current capacity.</param>
/// <param name="reqCap">Required capacity.</param>
/// <returns>New capacity.</returns>
private static int Capacity(int curCap, int reqCap)
{
int newCap;
if (reqCap < 256)
newCap = 256;
else
{
newCap = curCap << 1;
if (newCap < reqCap)
newCap = reqCap;
}
return newCap;
}
/// <summary>
/// Unsafe memory copy routine.
/// </summary>
/// <param name="src">Source.</param>
/// <param name="dest">Destination.</param>
/// <param name="len">Length.</param>
private static void CopyMemory(byte* src, byte* dest, int len)
{
PlatformMemoryUtils.CopyMemory(src, dest, len);
}
/** <inheritdoc /> */
public void WriteByte(byte val)
{
int pos0 = EnsureWriteCapacityAndShift(1);
_data[pos0] = val;
}
/** <inheritdoc /> */
public byte ReadByte()
{
int pos0 = EnsureReadCapacityAndShift(1);
return _data[pos0];
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteByteArray(byte[] val)
{
int pos0 = EnsureWriteCapacityAndShift(val.Length);
fixed (byte* data0 = _data)
{
WriteByteArray0(val, data0 + pos0);
}
}
/** <inheritdoc /> */
public byte[] ReadByteArray(int cnt)
{
int pos0 = EnsureReadCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
return ReadByteArray0(cnt, data0 + pos0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteBoolArray(bool[] val)
{
int pos0 = EnsureWriteCapacityAndShift(val.Length);
fixed (byte* data0 = _data)
{
WriteBoolArray0(val, data0 + pos0);
}
}
/** <inheritdoc /> */
public bool[] ReadBoolArray(int cnt)
{
int pos0 = EnsureReadCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
return ReadBoolArray0(cnt, data0 + pos0);
}
}
/** <inheritdoc /> */
public void WriteShort(short val)
{
int pos0 = EnsureWriteCapacityAndShift(2);
fixed (byte* data0 = _data)
{
WriteShort0(val, data0 + pos0);
}
}
/** <inheritdoc /> */
public short ReadShort()
{
int pos0 = EnsureReadCapacityAndShift(2);
fixed (byte* data0 = _data)
{
return ReadShort0(data0 + pos0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteShortArray(short[] val)
{
int cnt = val.Length << 1;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteShortArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public short[] ReadShortArray(int cnt)
{
int cnt0 = cnt << 1;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadShortArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteCharArray(char[] val)
{
int cnt = val.Length << 1;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteCharArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public char[] ReadCharArray(int cnt)
{
int cnt0 = cnt << 1;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadCharArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
public void WriteInt(int val)
{
int pos0 = EnsureWriteCapacityAndShift(4);
fixed (byte* data0 = _data)
{
WriteInt0(val, data0 + pos0);
}
}
/** <inheritdoc /> */
public void WriteInt(int writePos, int val)
{
EnsureWriteCapacity(writePos + 4);
fixed (byte* data0 = _data)
{
WriteInt0(val, data0 + writePos);
}
}
/** <inheritdoc /> */
public int ReadInt()
{
int pos0 = EnsureReadCapacityAndShift(4);
fixed (byte* data0 = _data)
{
return ReadInt0(data0 + pos0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteIntArray(int[] val)
{
int cnt = val.Length << 2;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteIntArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public int[] ReadIntArray(int cnt)
{
int cnt0 = cnt << 2;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadIntArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteFloatArray(float[] val)
{
int cnt = val.Length << 2;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteFloatArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public float[] ReadFloatArray(int cnt)
{
int cnt0 = cnt << 2;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadFloatArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
public void WriteLong(long val)
{
int pos0 = EnsureWriteCapacityAndShift(8);
fixed (byte* data0 = _data)
{
WriteLong0(val, data0 + pos0);
}
}
/** <inheritdoc /> */
public long ReadLong()
{
int pos0 = EnsureReadCapacityAndShift(8);
fixed (byte* data0 = _data)
{
return ReadLong0(data0 + pos0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteLongArray(long[] val)
{
int cnt = val.Length << 3;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteLongArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public long[] ReadLongArray(int cnt)
{
int cnt0 = cnt << 3;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadLongArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public void WriteDoubleArray(double[] val)
{
int cnt = val.Length << 3;
int pos0 = EnsureWriteCapacityAndShift(cnt);
fixed (byte* data0 = _data)
{
WriteDoubleArray0(val, data0 + pos0, cnt);
}
}
/** <inheritdoc /> */
public double[] ReadDoubleArray(int cnt)
{
int cnt0 = cnt << 3;
int pos0 = EnsureReadCapacityAndShift(cnt0);
fixed (byte* data0 = _data)
{
return ReadDoubleArray0(cnt, data0 + pos0, cnt0);
}
}
/** <inheritdoc /> */
public int WriteString(char* chars, int charCnt, int byteCnt, Encoding encoding)
{
int pos0 = EnsureWriteCapacityAndShift(byteCnt);
int written;
fixed (byte* data0 = _data)
{
written = BinaryUtils.StringToUtf8Bytes(chars, charCnt, byteCnt, encoding, data0 + pos0);
}
return written;
}
/** <inheritdoc /> */
public void Write(byte* src, int cnt)
{
EnsureWriteCapacity(_pos + cnt);
fixed (byte* data0 = _data)
{
WriteInternal(src, cnt, data0);
}
ShiftWrite(cnt);
}
/** <inheritdoc /> */
public void Read(byte* dest, int cnt)
{
fixed (byte* data0 = _data)
{
ReadInternal(data0, dest, cnt);
}
}
/** <inheritdoc /> */
public byte[] GetArray()
{
return _data;
}
/** <inheritdoc /> */
public bool CanGetArray
{
get { return true; }
}
/** <inheritdoc /> */
public byte[] GetArrayCopy()
{
byte[] copy = new byte[_pos];
Buffer.BlockCopy(_data, 0, copy, 0, _pos);
return copy;
}
/** <inheritdoc /> */
public bool IsSameArray(byte[] arr)
{
return _data == arr;
}
/** <inheritdoc /> */
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
public T Apply<TArg, T>(IBinaryStreamProcessor<TArg, T> proc, TArg arg)
{
Debug.Assert(proc != null);
fixed (byte* data0 = _data)
{
return proc.Invoke(data0, arg);
}
}
/// <summary>
/// Ensure capacity for write.
/// </summary>
/// <param name="cnt">Bytes count.</param>
private void EnsureWriteCapacity(int cnt)
{
if (cnt > _data.Length)
{
int newCap = Capacity(_data.Length, cnt);
byte[] data0 = new byte[newCap];
// Copy the whole initial array length here because it can be changed
// from Java without position adjusting.
Buffer.BlockCopy(_data, 0, data0, 0, _data.Length);
_data = data0;
}
}
/// <summary>
/// Ensure capacity for write and shift position.
/// </summary>
/// <param name="cnt">Bytes count.</param>
/// <returns>Position before shift.</returns>
private void EnsureReadCapacity(int cnt)
{
if (_data.Length - _pos < cnt)
throw new EndOfStreamException("Not enough data in stream [expected=" + cnt +
", remaining=" + (_data.Length - _pos) + ']');
}
}
}