예제 #1
0
        /// <summary>
        /// Writes an IEEE 754 double-precision (64-bit) floating-point number to the buffer
        /// </summary>
        internal static unsafe void WriteDoubleBE(FunctionObject ctx, ScriptObject instance, BoxedValue number, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!number.IsNumber || !offset.IsNumber)
                throw new ArgumentException("Buffer attempted to write NaN value or on an unspecified offset.");

            // Convert
            var value = Convert.ToDouble(number.Number);
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            // Make sure we have a spare buffer
            if (BufferObject.Temp == null)
                BufferObject.Temp = new byte[20];

            // Write unsafely directly
            fixed (byte* pBuffer = BufferObject.Temp)
                *((double*)(pBuffer)) = value;

            // Which way should we write?
            if (BitConverter.IsLittleEndian)
            {
                // We have to reverse
                array[index] = BufferObject.Temp[7];
                array[index + 1] = BufferObject.Temp[6];
                array[index + 2] = BufferObject.Temp[5];
                array[index + 3] = BufferObject.Temp[4];
                array[index + 4] = BufferObject.Temp[3];
                array[index + 5] = BufferObject.Temp[2];
                array[index + 6] = BufferObject.Temp[1];
                array[index + 7] = BufferObject.Temp[0];
            }
            else
            {
                // We have it in order
                array[index] = BufferObject.Temp[0];
                array[index + 1] = BufferObject.Temp[1];
                array[index + 2] = BufferObject.Temp[2];
                array[index + 3] = BufferObject.Temp[3];
                array[index + 4] = BufferObject.Temp[4];
                array[index + 5] = BufferObject.Temp[5];
                array[index + 6] = BufferObject.Temp[6];
                array[index + 7] = BufferObject.Temp[7];
            }
        }
예제 #2
0
        /// <summary>
        /// Decodes and returns a string from buffer data encoded with encoding (defaults to 'utf8') beginning at start (defaults to 0) and ending at end (defaults to buffer.length).
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        /// <param name="encodingName">The encoding for the to string conversion.</param>
        /// <param name="start">The starting offset for the to string conversion.</param>
        /// <param name="end">The ending offset for the to string conversion.</param>
        internal static string ToString(FunctionObject ctx, ScriptObject instance, BoxedValue encodingName, BoxedValue start, BoxedValue end)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();

            // Attempt to get the encoding
            Encoding encoding = encodingName.IsString
                ? TextEncoding.GetEncoding(encodingName.String)
                : null;

            // Default the encoding to utf8
            if (encoding == null)
                encoding = TextEncoding.UTF8;

            // Start offset defaults at zero
            int startOffset = start.IsNumber
                ? (int)start.Number
                : 0;

            // End offset is calculated from start offset
            int endOffset = end.IsNumber
                ? (int)end.Number
                : buffer.Count - startOffset;

            // Validate the range
            if (startOffset < 0 || endOffset > buffer.Count)
                throw new ArgumentOutOfRangeException("Index was out of range. Must be non-negative and less than the size of the Buffer.");

            // As we are using a segment, we need to use the appropriate offset
            startOffset += buffer.Offset;
            endOffset += buffer.Offset;

            // Size that needs to be converted
            var size = endOffset - startOffset;
            var chars = new char[size];

            // Copy bytes to a char array
            System.Array.Copy(buffer.Array, startOffset, chars, 0, size);

            // Return a string
            return TextEncoding.UTF8.GetString(
                encoding.GetBytes(chars)
                );
        }
예제 #3
0
        /// <summary>
        /// ReturnsWrites string to the buffer at offset using the given encoding. offset defaults to 0, encoding 
        /// defaults to 'utf8'. length is the number of bytes to write. Returns number of octets written. If buffer
        /// did not contain enough space to fit the entire string, it will write a partial amount of the string. 
        /// length defaults to buffer.length - offset. The method will not write partial characters.
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        /// <param name="text">Data to be written to buffer</param>
        /// <param name="offset">The starting offset.</param>
        /// <param name="length">The amount of characters to write.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <returns>The number of characters written.</returns>
        internal static int Write(FunctionObject ctx, ScriptObject instance, string text, BoxedValue offset, BoxedValue length, BoxedValue encodingName)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();
            var array = buffer.Array;

            // Start offset defaults at zero
            int startOffset = offset.IsNumber
                ? (int)offset.Number
                : 0;

            // End offset is calculated from start offset
            int endOffset = length.IsNumber
                ? (int)length.Number
                : buffer.Count - startOffset;

            // Attempt to get the encoding
            Encoding encoding = encodingName.IsString
                ? TextEncoding.GetEncoding(encodingName.String)
                : null;

            // Default the encoding to utf8
            if (encoding == null)
                encoding = TextEncoding.UTF8;

            // As we are using a segment, we need to use the appropriate offset
            startOffset += buffer.Offset;
            endOffset += buffer.Offset;

            // Write to the array
            int count = 0;
            for (int i = startOffset; i < endOffset; ++i, ++count)
                array[i] = Convert.ToByte(text[count]);

            // Put the amount of characters written
            buffer.Put("_charsWritten", count);

            // Return the amount of written characters
            return count;
        }
예제 #4
0
        /// <summary>
        /// Returns a new buffer which references the same memory as the old, but offset and cropped by the start (defaults to 0) and end (defaults to buffer.length) indexes. Negative indexes start from the end of the buffer.
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        internal static BufferObject Slice(FunctionObject ctx, ScriptObject instance,  BoxedValue start, BoxedValue end)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();
            var source = buffer.Array;

            // Start offset defaults to zero
            int startOffset = start.IsNumber
                ? (int)start.Number
                : 0;

            // End offset defaults to buffer.length
            int endOffset = end.IsNumber
                ? (int)end.Number
                : buffer.Count;

            // Validate the range
            if (startOffset < 0 || endOffset > buffer.Count)
                throw new ArgumentOutOfRangeException("Index was out of range. Must be non-negative and less than the size of the Buffer.");

            // As we are using a segment, we need to use the appropriate offset
            startOffset += buffer.Offset;
            endOffset += buffer.Offset;

            // Create the segment & get the prototype
            var segment = new ArraySegment<byte>(source, startOffset, endOffset - startOffset);

            // Return a new instance of a buffer
            return new BufferObject(segment, ctx.Env);
        }
예제 #5
0
        /// <summary>
        /// Returns a JSON-representation of the Buffer instance, which is identical to the output for JSON Arrays. JSON.stringify implicitly calls this function when stringifying a Buffer instance.
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        /// <returns>Returns a JSON-representation of the Buffer instance.</returns>
        internal static string ToJSON(FunctionObject ctx, ScriptObject instance)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();
            var array  = buffer.Array;
            var offset = buffer.Offset;
            var end    = buffer.Offset + buffer.Count;

            var writer = new StringBuilder();
            writer.Append('[');
            try
            {
                for (int i = offset; i < end; ++i)
                {
                    writer.Append(array[i]);
                    if (i < (array.Length - 1))
                        writer.Append(',');
                }
            }
            catch { }
            writer.Append(']');
            return writer.ToString();
        }
예제 #6
0
        /// <summary>
        /// Performs a read from the underlying stream.
        /// </summary>
        /// <returns>Returns value read.</returns>
        internal static BoxedValue ReadUInt64LE(FunctionObject ctx, ScriptObject instance, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!offset.IsNumber || (offset.Number + 8) > buffer.Count)
                throw new ArgumentException("Attempt to read on an invalid offset.");

            // Convert and check the limits
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            return BoxedValue.Box((ulong)(
                (array[index + 7] << 56) |
                (array[index + 6] << 48) |
                (array[index + 5] << 40) |
                (array[index + 4] << 32) |
                (array[index + 3] << 24) |
                (array[index + 2] << 16) |
                (array[index + 1] << 8) |
                (array[index])
                ));
        }
예제 #7
0
        /// <summary>
        /// Performs a read from the underlying stream.
        /// </summary>
        /// <returns>Returns value read.</returns>
        internal static BoxedValue ReadUInt8(FunctionObject ctx, ScriptObject instance, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!offset.IsNumber || (offset.Number + 1) > buffer.Count)
                throw new ArgumentException("Attempt to read on an invalid offset.");

            // Convert and check the limits
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            return BoxedValue.Box(array[index]);
        }
예제 #8
0
        /// <summary>
        /// Reads an IEEE 754 single-precision (32-bit) floating-point number from the buffer
        /// </summary>
        internal static unsafe BoxedValue ReadFloatLE(FunctionObject ctx, ScriptObject instance, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!offset.IsNumber || (offset.Number + 4) > buffer.Count)
                throw new ArgumentException("Attempt to read on an invalid offset.");

            // Convert and check the limits
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            // Make sure we have a spare buffer
            if (BufferObject.Temp == null)
                BufferObject.Temp = new byte[20];

            // Which way should we write?
            if (!BitConverter.IsLittleEndian)
            {
                // We have to reverse
                BufferObject.Temp[3] = array[index];
                BufferObject.Temp[2] = array[index + 1];
                BufferObject.Temp[1] = array[index + 2];
                BufferObject.Temp[0] = array[index + 3];
            }
            else
            {
                // We have it in order
                BufferObject.Temp[0] = array[index];
                BufferObject.Temp[1] = array[index + 1];
                BufferObject.Temp[2] = array[index + 2];
                BufferObject.Temp[3] = array[index + 3];
            }

            // Read the value from the buffer
            float value = 0;
            fixed (byte* pBuffer = BufferObject.Temp)
                value = *((float*)(pBuffer));

            return BoxedValue.Box(value);
        }
예제 #9
0
        /// <summary>
        /// Decodes and returns a string from buffer data encoded with encoding (defaults to 'utf8') beginning at start (defaults to 0) and ending at end (defaults to buffer.length).
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        /// <param name="fillValue">The value to fill.</param>
        /// <param name="start">The starting offset for the to string conversion.</param>
        /// <param name="end">The ending offset for the to string conversion.</param>
        internal static void Fill(FunctionObject ctx, ScriptObject instance, BoxedValue fillValue, BoxedValue start, BoxedValue end)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();

            // Start offset defaults at zero
            byte fill = fillValue.IsNumber
                ? (byte)fillValue.Number
                : (byte)0;

            // Start offset defaults at zero
            int startOffset = start.IsNumber
                ? (int)start.Number
                : 0;

            // End offset is calculated from start offset
            int endOffset = end.IsNumber
                ? (int)end.Number
                : buffer.Count - startOffset;

            // Validate the range
            if (startOffset < 0 || endOffset > buffer.Count)
                throw new ArgumentOutOfRangeException("Index was out of range. Must be non-negative and less than the size of the Buffer.");

            // As we are using a segment, we need to use the appropriate offset
            startOffset += buffer.Offset;
            endOffset += buffer.Offset;

            // Fill
            for (int i = startOffset; i < endOffset; ++i)
                buffer.Buffer.Array[i] = fill;
        }
예제 #10
0
        /// <summary>
        /// Does copy between buffers. The source and target regions can be overlapped. targetStart and sourceStart default to 0. sourceEnd defaults to buffer.length.
        /// </summary>
        /// <param name="ctx">The function context.</param>
        /// <param name="instance">The object instance.</param>
        internal static void Copy(FunctionObject ctx, ScriptObject instance, BufferObject targetBuffer, BoxedValue targetStart, BoxedValue sourceStart, BoxedValue sourceEnd)
        {
            // Get the buffer
            var buffer = instance.CastTo<BufferObject>();

            // Get source and target arrays
            var source = buffer.Array;
            var target = targetBuffer.Array;

            // Start offset defaults to zero
            int targetStartOffset = targetStart.IsNumber
                ? (int)targetStart.Number
                : 0;

            // Start offset defaults to zero
            int sourceStartOffset = sourceStart.IsNumber
                ? (int)sourceStart.Number
                : 0;

            // End offset defaults to buffer.length
            int sourceEndOffset = sourceEnd.IsNumber
                ? (int)sourceEnd.Number
                : buffer.Count;

            // As we are using a segment, we need to use the appropriate offset
            sourceStartOffset += buffer.Offset;
            sourceEndOffset += buffer.Offset;
            targetStartOffset += targetBuffer.Offset;

            // Get the length
            var size = sourceEndOffset - sourceStartOffset;

            // Block copy from one array to another
            System.Buffer.BlockCopy(source, sourceStartOffset, target, targetStartOffset, size);
        }
예제 #11
0
        /// <summary>
        /// Writes a 1-byte unsigned integer value to the underlying stream.
        /// </summary>
        internal static void WriteUInt8(FunctionObject ctx, ScriptObject instance, BoxedValue number, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!number.IsNumber || !offset.IsNumber)
                throw new ArgumentException("Buffer attempted to write NaN value or on an unspecified offset.");

            // Convert
            var value = Convert.ToByte(number.Number);
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            // Write to the offset
            array[index] = value;
        }
예제 #12
0
        /// <summary>
        /// Writes a 8-byte unsigned integer value to the underlying stream.
        /// </summary>
        internal static void WriteUInt64LE(FunctionObject ctx, ScriptObject instance, BoxedValue number, BoxedValue offset)
        {
            // Get the buffer and the appropriate offset
            var buffer = instance.CastTo<BufferObject>();
            if (!number.IsNumber || !offset.IsNumber)
                throw new ArgumentException("Buffer attempted to write NaN value or on an unspecified offset.");

            // Convert
            var value = Convert.ToUInt64(number.Number);
            var index = buffer.Offset + (int)offset.Number;
            var array = buffer.Array;

            array[index] = (byte)((value) & 0xFF);
            array[index + 1] = (byte)((value >> 8) & 0xFF);
            array[index + 2] = (byte)((value >> 16) & 0xFF);
            array[index + 3] = (byte)((value >> 24) & 0xFF);
            array[index + 4] = (byte)((value >> 32) & 0xFF);
            array[index + 5] = (byte)((value >> 40) & 0xFF);
            array[index + 6] = (byte)((value >> 48) & 0xFF);
            array[index + 7] = (byte)((value >> 56) & 0xFF);
        }