/// <summary> /// Add an array of type T to the buffer (aligns the data and grows if necessary). /// </summary> /// <typeparam name="T">The type of the input data</typeparam> /// <param name="x">The array to copy data from</param> public void Add <T>(T[] x) where T : struct { if (x == null) { throw new ArgumentNullException("Cannot add a null array"); } if (x.Length == 0) { // don't do anything if the array is empty return; } if (!ByteBuffer.IsSupportedType <T>()) { throw new ArgumentException("Cannot add this Type array to the builder"); } int size = ByteBuffer.SizeOf <T>(); // Need to prep on size (for data alignment) and then we pass the // rest of the length (minus 1) as additional bytes Prep(size, size * (x.Length - 1)); Put(x); }
/// <summary> /// Add a span of type T to the buffer (aligns the data and grows if necessary). /// </summary> /// <typeparam name="T">The type of the input data</typeparam> /// <param name="x">The span to copy data from</param> public void Add <T>(Span <T> x) where T : struct { if (!ByteBuffer.IsSupportedType <T>()) { throw new ArgumentException("Cannot add this Type array to the builder"); } int size = ByteBuffer.SizeOf <T>(); // Need to prep on size (for data alignment) and then we pass the // rest of the length (minus 1) as additional bytes Prep(size, size * (x.Length - 1)); Put(x); }
/// <summary> /// Copies an array segment of type T into this buffer, ending at the /// given offset into this buffer. The starting offset is calculated /// based on the count of the array segment and is the value returned. /// </summary> /// <typeparam name="T">The type of the input data (must be a struct) /// </typeparam> /// <param name="offset">The offset into this buffer where the copy /// will end</param> /// <param name="x">The array segment to copy data from</param> /// <returns>The 'start' location of this buffer now, after the copy /// completed</returns> public int Put <T>(int offset, ArraySegment <T> x) where T : struct { if (x.Equals(default(ArraySegment <T>))) { throw new ArgumentNullException("Cannot put a uninitialized array segment"); } if (x.Count == 0) { throw new ArgumentException("Cannot put an empty array"); } if (!IsSupportedType <T>()) { throw new ArgumentException("Cannot put an array of type " + typeof(T) + " into this buffer"); } if (BitConverter.IsLittleEndian) { int numBytes = ByteBuffer.ArraySize(x); offset -= numBytes; AssertOffsetAndLength(offset, numBytes); // if we are LE, just do a block copy #if ENABLE_SPAN_T && (UNSAFE_BYTEBUFFER || NETSTANDARD2_1) MemoryMarshal.Cast <T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes)); #else var srcOffset = ByteBuffer.SizeOf <T>() * x.Offset; Buffer.BlockCopy(x.Array, srcOffset, _buffer.Buffer, offset, numBytes); #endif } else { throw new NotImplementedException("Big Endian Support not implemented yet " + "for putting typed arrays"); // if we are BE, we have to swap each element by itself //for(int i = x.Length - 1; i >= 0; i--) //{ // todo: low priority, but need to genericize the Put<T>() functions //} } return(offset); }
/// <summary> /// Adds the data of type T pointed to by the given pointer to the buffer (aligns the data and grows if necessary). /// </summary> /// <typeparam name="T">The type of the input data</typeparam> /// <param name="ptr">The pointer to copy data from</param> /// <param name="sizeInBytes">The data size in bytes</param> public void Add <T>(IntPtr ptr, int sizeInBytes) where T : struct { if (sizeInBytes == 0) { // don't do anything if the array is empty return; } if (ptr == IntPtr.Zero) { throw new ArgumentNullException("Cannot add a null pointer"); } if (sizeInBytes < 0) { throw new ArgumentOutOfRangeException("sizeInBytes", "sizeInBytes cannot be negative"); } if (!ByteBuffer.IsSupportedType <T>()) { throw new ArgumentException("Cannot add this Type array to the builder"); } int size = ByteBuffer.SizeOf <T>(); if ((sizeInBytes % size) != 0) { throw new ArgumentException("The given size in bytes " + sizeInBytes + " doesn't match the element size of T ( " + size + ")", "sizeInBytes"); } // Need to prep on size (for data alignment) and then we pass the // rest of the length (minus 1) as additional bytes Prep(size, sizeInBytes - size); Put <T>(ptr, sizeInBytes); }