Exemple #1
0
        private unsafe ValueTask <int> ReadAsyncInternal(Memory <byte> destination, CancellationToken cancellationToken)
        {
            if (!CanRead)
            {
                ThrowHelper.ThrowNotSupportedException_UnreadableStream();
            }

            long positionBefore = _filePosition;

            if (CanSeek)
            {
                long len = Length;
                if (positionBefore + destination.Length > len)
                {
                    destination = positionBefore <= len?
                                  destination.Slice(0, (int)(len - positionBefore)) :
                                      default;
                }

                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it
                // ourselves, but only in memory. This isn't threadsafe.
                _filePosition += destination.Length;
            }

            (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, positionBefore, cancellationToken);
            return(vts != null
                ? new ValueTask <int>(vts, vts.Version)
                : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException <int>(HandleIOError(positionBefore, errorCode)));
        }
Exemple #2
0
 public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options)
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write, options: options))
     {
         AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.ReadAsync(handle, buffers: null, 0));
     }
 }
Exemple #3
0
 /// <summary>
 /// 写入二进制文件。
 /// </summary>
 /// <param name="path">给定的文件路径。</param>
 /// <param name="buffer">给定的字节数组。</param>
 /// <param name="fileOffset">给定的读取偏移量。</param>
 public static void WriteBinaryFile(this string path, byte[] buffer, long fileOffset)
 {
     using (var handle = File.OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read))
     {
         RandomAccess.Write(handle, buffer, fileOffset);
     }
 }
Exemple #4
0
        /// <summary>
        /// Instantiates a new TIME from the given binary reader.
        /// </summary>
        /// <remarks>
        /// The byte stream is read in the following order:
        /// <list type="bullet">
        /// <item>Centiseconds</item>
        /// <item>Seconds</item>
        /// <item>Minutes</item>
        /// <item>Hours</item>
        /// </list>
        /// </remarks>
        /// <param name="rx"></param>
        public TpsTime(RandomAccess rx)
        {
            if (rx == null)
            {
                throw new ArgumentNullException(nameof(rx));
            }

            // Time, mask encoded

            int time = rx.LongLE();

            // Hours 0 - 23
            int hours = (time & 0x7F000000) >> 24;

            // Minutes 0 - 59
            int mins = (time & 0x00FF0000) >> 16;

            // Seconds 0 - 59
            int secs = (time & 0x0000FF00) >> 8;

            // Centiseconds (seconds/100) 0 - 99
            int centi = time & 0x000000FF;

            Value = new TimeSpan(0, hours, mins, secs, centi * 10);
        }
Exemple #5
0
 public void ReturnsZeroForEmptyFile()
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write))
     {
         Assert.Equal(0, RandomAccess.GetLength(handle));
     }
 }
Exemple #6
0
 public void ThrowsOnReadAccess(FileOptions options)
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options))
     {
         Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Write(handle, new byte[1], 0));
     }
 }
        public void ShouldParseBCD(string value, int bcdLength, int bcdDigitsAfterDecimal, byte[] data)
        {
            var rx  = new RandomAccess(data);
            var bcd = rx.BinaryCodedDecimal(bcdLength, bcdDigitsAfterDecimal);

            Assert.AreEqual(value, bcd);
        }
Exemple #8
0
        public TpsHeader(RandomAccess rx)
        {
            Data = rx ?? throw new ArgumentNullException(nameof(rx));

            Address = rx.LongLE();

            if (Address != 0)
            {
                throw new NotATopSpeedFileException("File does not start with 0x00000000. It is not a TopSpeed file or it may be encrypted.");
            }

            HeaderSize = rx.ShortLE();

            var header = rx.Read(HeaderSize - 6);

            FileLength1             = header.LongLE();
            FileLength2             = header.LongLE();
            MagicNumber             = header.FixedLengthString(4);
            Zeroes                  = header.ShortLE();
            LastIssuedRow           = header.LongBE();
            Changes                 = header.LongLE();
            ManagementPageReference = header.ToFileOffset(header.LongLE());

            PageStart = header.ToFileOffset(header.LongArrayLE((0x110 - 0x20) / 4));
            PageEnd   = header.ToFileOffset(header.LongArrayLE((0x200 - 0x110) / 4));
        }
Exemple #9
0
 /// <summary>Create a tiler.</summary>
 /// <param name="f">The random access device from which image data may be read.
 /// This may be null if the tile information is available from memory.</param>
 /// <param name="fileOffset">The file offset within the RandomAccess device at which
 /// the data begins.</param>
 /// <param name="dims">The actual dimensions of the image.</param>
 /// <param name="base_Renamed">base class (should be a primitive type) of the image.</param>
 public ImageTiler(RandomAccess f, long fileOffset, int[] dims, Type base_Renamed)
 {
     this.f            = f;
     this.fileOffset   = fileOffset;
     this.dims         = dims;
     this.base_Renamed = base_Renamed;
 }
        public async Task ReadAsyncUsingSingleBuffer()
        {
            const int fileSize = 1_000_000; // 1 MB
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize))
                {
                    int current = 0;
                    int total   = 0;

                    // From https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering:
                    // "File access sizes, including the optional file offset in the OVERLAPPED structure,
                    // if specified, must be for a number of bytes that is an integer multiple of the volume sector size."
                    // So if buffer and physical sector size is 4096 and the file size is 4097:
                    // the read from offset=0 reads 4096 bytes
                    // the read from offset=4096 reads 1 byte
                    // the read from offset=4097 THROWS (Invalid argument, offset is not a multiple of sector size!)
                    // That is why we stop at the first incomplete read (the next one would throw).
                    // It's possible to get 0 if we are lucky and file size is a multiple of physical sector size.
                    do
                    {
                        current = await RandomAccess.ReadAsync(handle, buffer.Memory, fileOffset : total);

                        Assert.True(expected.AsSpan(total, current).SequenceEqual(buffer.GetSpan().Slice(0, current)));

                        total += current;
                    }while (current == buffer.Memory.Length);

                    Assert.Equal(fileSize, total);
                }
        }
Exemple #11
0
        public async Task WritesBytesFromGivenBufferToGivenFileAtGivenOffsetAsync()
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous))
            {
                int total   = 0;
                int current = 0;

                while (total != fileSize)
                {
                    Memory <byte> buffer = content.AsMemory(total, Math.Min(content.Length - total, fileSize / 4));

                    current = await RandomAccess.WriteAsync(handle, buffer, fileOffset : total);

                    Assert.InRange(current, 0, buffer.Length);

                    total += current;
                }
            }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #12
0
 public async Task WriteUsingEmptyBufferReturnsZeroAsync()
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: FileOptions.Asynchronous))
     {
         Assert.Equal(0, await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset: 0));
     }
 }
Exemple #13
0
        public void ShouldReadFromRandomAccess(string value, int bcdLength, int bcdDigitsAfterDecimal, byte[] data)
        {
            var rx  = new RandomAccess(data);
            var dec = new TpsDecimal(rx, bcdLength, bcdDigitsAfterDecimal);

            Assert.AreEqual(value, dec.Value);
        }
        public IndexDefinitionRecord(RandomAccess rx)
        {
            if (rx == null)
            {
                throw new ArgumentNullException(nameof(rx));
            }

            ExternalFile = rx.ZeroTerminatedString();

            if (ExternalFile.Length == 0)
            {
                int read = rx.Byte();

                if (read != 0x01)
                {
                    throw new ArgumentException($"Bad index definition: missing 0x01 after zero string ({read:X2})");
                }
            }

            Name        = rx.ZeroTerminatedString();
            Flags       = rx.Byte();
            FieldsInKey = rx.ShortLE();

            KeyField     = new int[FieldsInKey];
            KeyFieldFlag = new int[FieldsInKey];

            for (int i = 0; i < FieldsInKey; i++)
            {
                KeyField[i]     = rx.ShortLE();
                KeyFieldFlag[i] = rx.ShortLE();
            }
        }
        public void ShouldParseByte(byte value, byte[] data)
        {
            var  rx     = new RandomAccess(data);
            byte parsed = rx.Byte();

            Assert.AreEqual(value, parsed);
        }
Exemple #16
0
        public DataHeader(RandomAccess rx)
            : base(rx)
        {
            AssertIsType(0xF3);

            RecordNumber = rx.LongBE();
        }
        public void ShouldReuseBuffer()
        {
            var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 });

            ra.Byte();
            var read = ra.Read(3);

            Assert.AreEqual(3, read.Length);
            Assert.AreEqual(0, read.Position);
            Assert.AreEqual(2, read.Byte());
            Assert.AreEqual(3, read.Byte());
            Assert.AreEqual(4, read.Byte());

            read.JumpAbsolute(0);
            Assert.AreEqual(2, read.Byte());

            read.JumpRelative(1);
            Assert.AreEqual(4, read.Byte());

            read.JumpAbsolute(1);

            var read2 = read.Read(2);

            Assert.AreEqual(2, read2.Length);
            Assert.AreEqual(0, read2.Position);
            Assert.AreEqual(3, read2.Byte());
            Assert.AreEqual(4, read2.Byte());
        }
Exemple #18
0
        public FieldDefinitionRecord(RandomAccess rx)
        {
            if (rx == null)
            {
                throw new ArgumentNullException(nameof(rx));
            }

            Type         = (TpsTypeCode)rx.Byte();
            Offset       = rx.ShortLE();
            FullName     = rx.ZeroTerminatedString();
            ElementCount = rx.ShortLE();
            Length       = rx.ShortLE();
            Flags        = rx.ShortLE();
            Index        = rx.ShortLE();

            switch (Type)
            {
            case TpsTypeCode.Decimal:
                BcdDigitsAfterDecimalPoint = rx.Byte();
                BcdElementLength           = rx.Byte();
                break;

            case TpsTypeCode.String:
            case TpsTypeCode.CString:
            case TpsTypeCode.PString:
                StringLength = rx.ShortLE();
                StringMask   = rx.ZeroTerminatedString();
                if (StringMask.Length == 0)
                {
                    rx.Byte();
                }
                break;
            }
        }
        public void ShouldParseShortLittleEndian(short value, byte[] data)
        {
            var   rx     = new RandomAccess(data);
            short parsed = rx.ShortLE();

            Assert.AreEqual(value, parsed);
        }
Exemple #20
0
            static async Task Validate(SafeFileHandle handle, FileOptions options, bool[] syncWrites, bool[] syncReads)
            {
                byte[] writeBuffer = new byte[1];
                byte[] readBuffer  = new byte[2];
                long   fileOffset  = 0;

                foreach (bool syncWrite in syncWrites)
                {
                    foreach (bool syncRead in syncReads)
                    {
                        writeBuffer[0] = (byte)fileOffset;

                        if (syncWrite)
                        {
                            RandomAccess.Write(handle, writeBuffer, fileOffset);
                        }
                        else
                        {
                            await RandomAccess.WriteAsync(handle, writeBuffer, fileOffset);
                        }

                        Assert.Equal(writeBuffer.Length, syncRead ? RandomAccess.Read(handle, readBuffer, fileOffset) : await RandomAccess.ReadAsync(handle, readBuffer, fileOffset));

                        Assert.Equal(writeBuffer[0], readBuffer[0]);

                        fileOffset += 1;
                    }
                }
            }
        public void ShouldParseLongLittleEndian(int value, byte[] data)
        {
            var rx     = new RandomAccess(data);
            var parsed = rx.LongLE();

            Assert.AreEqual(value, parsed);
        }
        public async Task ReadWriteAsyncUsingMultipleBuffers(bool memoryPageSized)
        {
            string filePath = GetTestFilePath();
            // We test with buffers both one and two memory pages long. In the former case,
            // the I/O operations will issue one scatter/gather API call, and in the latter
            // case they will issue multiple calls; one per buffer. The buffers must still
            // be aligned to comply with FILE_FLAG_NO_BUFFERING's requirements.
            int bufferSize = Environment.SystemPageSize * (memoryPageSized ? 1 : 2);
            int fileSize   = bufferSize * 2;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(fileSize))
                {
                    Memory <byte> firstHalf  = buffer.Memory.Slice(0, bufferSize);
                    Memory <byte> secondHalf = buffer.Memory.Slice(bufferSize);

                    content.AsSpan().CopyTo(buffer.GetSpan());
                    await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { firstHalf, secondHalf }, 0);

                    buffer.GetSpan().Clear();
                    long nRead = await RandomAccess.ReadAsync(handle, new Memory <byte>[] { firstHalf, secondHalf }, 0);

                    Assert.Equal(buffer.GetSpan().Length, nRead);
                    AssertExtensions.SequenceEqual(buffer.GetSpan(), content.AsSpan());
                }
        }
 /// <summary>Create a tiler.</summary>
 /// <param name="f">The random access device from which image data may be read.
 /// This may be null if the tile information is available from memory.</param>
 /// <param name="fileOffset">The file offset within the RandomAccess device at which
 /// the data begins.</param>
 /// <param name="dims">The actual dimensions of the image.</param>
 /// <param name="base_Renamed">base class (should be a primitive type) of the image.</param>
 public ImageTiler(RandomAccess f, long fileOffset, int[] dims, Type base_Renamed)
 {
     this.f = f;
     this.fileOffset = fileOffset;
     this.dims = dims;
     this.base_Renamed = base_Renamed;
 }
        public TableNameHeader(RandomAccess rx)
            : base(rx, readTable: false)
        {
            AssertIsType(0xFE);

            Name = rx.FixedLengthString(rx.Length - rx.Position);
        }
Exemple #25
0
 public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options)
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options))
     {
         AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0));
     }
 }
Exemple #26
0
 public async Task WriteUsingEmptyBufferReturnsAsync(FileOptions options)
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: options))
     {
         await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset : 0);
     }
 }
Exemple #27
0
        public async Task HappyPath(FileOptions options)
        {
            const int fileSize = 4_001;
            string    filePath = GetTestFilePath();

            byte[] expected = RandomNumberGenerator.GetBytes(fileSize);
            File.WriteAllBytes(filePath, expected);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options))
            {
                byte[] actual  = new byte[fileSize + 1];
                int    current = 0;
                int    total   = 0;

                do
                {
                    Memory <byte> buffer = actual.AsMemory(total, Math.Min(actual.Length - total, fileSize / 4));

                    current = await RandomAccess.ReadAsync(handle, buffer, fileOffset : total);

                    Assert.InRange(current, 0, buffer.Length);

                    total += current;
                } while (current != 0);

                Assert.Equal(fileSize, total);
                Assert.Equal(expected, actual.Take(total).ToArray());
            }
        }
Exemple #28
0
 public void ThrowsOnWriteAccess()
 {
     using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write))
     {
         Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new Memory <byte>[] { new byte[1] }, 0));
     }
 }
Exemple #29
0
        public async Task WriteAsyncUsingMultipleBuffers(bool async)
        {
            string filePath   = GetTestFilePath();
            int    bufferSize = Environment.SystemPageSize;
            int    fileSize   = bufferSize * 10;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer_1 = SectorAlignedMemory <byte> .Allocate(bufferSize))
                    using (SectorAlignedMemory <byte> buffer_2 = SectorAlignedMemory <byte> .Allocate(bufferSize))
                    {
                        long total = 0;

                        IReadOnlyList <ReadOnlyMemory <byte> > buffers = new ReadOnlyMemory <byte>[]
                        {
                            buffer_1.Memory,
                            buffer_2.Memory,
                        };

                        while (total != fileSize)
                        {
                            content.AsSpan((int)total, bufferSize).CopyTo(buffer_1.GetSpan());
                            content.AsSpan((int)total + bufferSize, bufferSize).CopyTo(buffer_2.GetSpan());

                            total += async
                        ? await RandomAccess.WriteAsync(handle, buffers, fileOffset : total)
                        : RandomAccess.Write(handle, buffers, fileOffset: total);
                        }
                    }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #30
0
 public void WriteUsingEmptyBufferReturnsZero()
 {
     using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write))
     {
         Assert.Equal(0, RandomAccess.Write(handle, Array.Empty <byte>(), fileOffset: 0));
     }
 }
Exemple #31
0
        public async Task WriteUsingSingleBuffer(bool async)
        {
            string filePath   = GetTestFilePath();
            int    bufferSize = Environment.SystemPageSize;
            int    fileSize   = bufferSize * 10;

            byte[] content = RandomNumberGenerator.GetBytes(fileSize);

            using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous | NoBuffering))
                using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(bufferSize))
                {
                    int total = 0;

                    while (total != fileSize)
                    {
                        int take = Math.Min(content.Length - total, bufferSize);
                        content.AsSpan(total, take).CopyTo(buffer.GetSpan());

                        if (async)
                        {
                            await RandomAccess.WriteAsync(handle, buffer.Memory, fileOffset : total);
                        }
                        else
                        {
                            RandomAccess.Write(handle, buffer.GetSpan(), fileOffset: total);
                        }

                        total += buffer.Memory.Length;
                    }
                }

            Assert.Equal(content, File.ReadAllBytes(filePath));
        }
Exemple #32
0
 internal ImageDataTiler(ImageData enclosingInstance, RandomAccess o, long offset, ArrayDesc d)
     : base(o, offset, d.dims, d.type)
 {
     InitBlock(enclosingInstance);
 }
Exemple #33
0
 protected void SetFileOffset(Object o)
 {
     if(o is RandomAccess)
       {
     fileOffset = FitsUtil.FindOffset(o);
     dataSize = TrueSize;
     input = (RandomAccess)o;
       }
 }