/// <summary> /// Initializes paging /// </summary> public static void Init() { // Flags PageFlags kernelFlags = PageFlags.Present | PageFlags.Writable; PageFlags usercodeFlags = PageFlags.Present | PageFlags.UserMode; PageFlags userFlags = PageFlags.Present | PageFlags.Writable | PageFlags.UserMode; // Bit array to store which frames are free bitmap = new BitArray(4096 * 1024 / 4); // Create a new page directory for the kernel // Note: At this point, virtual address == physical address due to identity mapping KernelDirectory = CreateNewDirectoryPhysically(userFlags); SetPageDirectory(KernelDirectory, KernelDirectory); // Identity map int end = (int)PhysicalMemoryManager.FirstFree(); for (int address = 0; address < end; address += 0x1000) { MapPage(KernelDirectory, address, address, kernelFlags); bitmap.SetBit(address / 0x1000); } // Usercode is a section that is code in the kernel available to usermode int usercode = (int)getUsercodeAddress(); MapPage(KernelDirectory, usercode, usercode, usercodeFlags); // Enable paging Enable(); }
/// <summary> /// Creates a new page directory using only physical memory (used in Init) /// </summary> /// <param name="flags">The flags</param> /// <returns>The page directory</returns> public static PageDirectory *CreateNewDirectoryPhysically(PageFlags flags) { // Allocate a new block of physical memory to store our physical page in PageDirectory *directory = (PageDirectory *)Heap.AlignedAlloc(0x1000, sizeof(PageDirectory)); directory->PhysicalDirectory = directory; if (directory == null) { Panic.DoPanic("directory == null"); } // Allocate the tables for (int i = 0; i < 1024; i++) { PageTable *table = (PageTable *)PhysicalMemoryManager.Alloc(); if (table == null) { Panic.DoPanic("table == null"); } Memory.Memclear(table, sizeof(PageTable)); // Note: At this point, virtual address == physical address due to identity mapping directory->PhysicalTables[i] = (int)table | (int)flags; directory->VirtualTables[i] = (int)table; } return(directory); }
internal static Page NewPage(Transaction tx, PageFlags flags, int num) { var page = tx.AllocatePage(num); page.Flags = flags; return(page); }
internal Page NewPage(PageFlags flags, int num) { var page = _tx.AllocatePage(num, flags); State.RecordNewPage(page, num); return(page); }
public PageHeader(File file, long position) { file.Seek(position); // An Ogg page header is at least 27 bytes, so we'll go ahead and read that // much and then get the rest when we're ready for it. ByteVector data = file.ReadBlock(27); if (data.Count < 27 || !data.StartsWith("OggS")) { throw new CorruptFileException("Error reading page header"); } _version = data [4]; _flags = (PageFlags)data [5]; _absolute_granular_position = data.Mid(6, 8).ToULong(false); _stream_serial_number = data.Mid(14, 4).ToUInt(false); _page_sequence_number = data.Mid(18, 4).ToUInt(false); // Byte number 27 is the number of page segments, which is the only variable // length portion of the page header. After reading the number of page // segments we'll then read in the coresponding data for this count. int page_segment_count = data [26]; ByteVector page_segments = file.ReadBlock(page_segment_count); // Another sanity check. if (page_segment_count < 1 || page_segments.Count != page_segment_count) { throw new CorruptFileException("Incorrect number of page segments"); } // The base size of an Ogg page 27 bytes plus the number of lacing values. _size = (uint)(27 + page_segment_count); _packet_sizes = new List <int> (); int packet_size = 0; _data_size = 0; for (int i = 0; i < page_segment_count; i++) { _data_size += page_segments [i]; packet_size += page_segments [i]; if (page_segments [i] < 255) { _packet_sizes.Add(packet_size); packet_size = 0; } } if (packet_size > 0) { _packet_sizes.Add(packet_size); } }
/// <summary> /// Maps a page in a directory /// </summary> /// <param name="directory">The page directory</param> /// <param name="phys">The physical address</param> /// <param name="virt">The virtual address</param> /// <param name="flags">The flags</param> public static void MapPage(PageDirectory *directory, int phys, int virt, PageFlags flags) { // Get indices int pageIndex = virt / 0x1000; int tableIndex = pageIndex / 1024; // Set page using its virtual address PageTable *table = (PageTable *)directory->VirtualTables[tableIndex]; table->Pages[pageIndex & (1024 - 1)] = ToFrameAddress(phys) | (int)flags; }
internal Page NewPage(PageFlags flags, int num) { Page page; using (IsFreeSpaceTree ? _tx.Environment.FreeSpaceHandling.Disable() : null) { page = _tx.AllocatePage(num, flags); } State.RecordNewPage(page, num); return(page); }
public PageHeader (uint streamSerialNumber, uint pageNumber, PageFlags flags) { _version = 0; _flags = flags; _absolute_granular_position = 0; _stream_serial_number = streamSerialNumber; _page_sequence_number = pageNumber; _size = 0; _data_size = 0; _packet_sizes = new List<int> (); if (pageNumber == 0 && (flags & PageFlags.FirstPacketContinued) == 0) _flags |= PageFlags.FirstPageOfStream; }
public PageHeader(File file, long position) { if (file == null) { throw new ArgumentNullException("file"); } if (position < 0 || position > file.Length - 27) { throw new ArgumentOutOfRangeException("position"); } file.Seek(position); ByteVector data = file.ReadBlock(27); if (data.Count < 27 || !data.StartsWith("OggS")) { throw new CorruptFileException("Error reading page header"); } version = data[4]; this.flags = (PageFlags)data[5]; absolute_granular_position = data.Mid(6, 8).ToULong(false); stream_serial_number = data.Mid(14, 4).ToUInt(false); page_sequence_number = data.Mid(18, 4).ToUInt(false); int page_segment_count = data[26]; ByteVector page_segments = file.ReadBlock(page_segment_count); if (page_segment_count < 1 || page_segments.Count != page_segment_count) { throw new CorruptFileException("Incorrect number of page segments"); } size = (uint)(27 + page_segment_count); packet_sizes = new List <int>(); int packet_size = 0; data_size = 0; for (int i = 0; i < page_segment_count; i++) { data_size += page_segments[i]; packet_size += page_segments[i]; if (page_segments[i] < 255) { packet_sizes.Add(packet_size); packet_size = 0; } } if (packet_size > 0) { packet_sizes.Add(packet_size); } }
public PageHeader (File file, long position) { file.Seek (position); // An Ogg page header is at least 27 bytes, so we'll go ahead and read that // much and then get the rest when we're ready for it. ByteVector data = file.ReadBlock (27); if (data.Count < 27 || !data.StartsWith ("OggS")) throw new CorruptFileException ("Error reading page header"); _version = data [4]; _flags = (PageFlags) data [5]; _absolute_granular_position = data.Mid( 6, 8).ToULong (false); _stream_serial_number = data.Mid(14, 4).ToUInt (false); _page_sequence_number = data.Mid(18, 4).ToUInt (false); // Byte number 27 is the number of page segments, which is the only variable // length portion of the page header. After reading the number of page // segments we'll then read in the coresponding data for this count. int page_segment_count = data [26]; ByteVector page_segments = file.ReadBlock (page_segment_count); // Another sanity check. if(page_segment_count < 1 || page_segments.Count != page_segment_count) throw new CorruptFileException ("Incorrect number of page segments"); // The base size of an Ogg page 27 bytes plus the number of lacing values. _size = (uint)(27 + page_segment_count); _packet_sizes = new List<int> (); int packet_size = 0; _data_size = 0; for (int i = 0; i < page_segment_count; i++) { _data_size += page_segments [i]; packet_size += page_segments [i]; if (page_segments [i] < 255) { _packet_sizes.Add (packet_size); packet_size = 0; } } if (packet_size > 0) _packet_sizes.Add (packet_size); }
public PageHeader(uint streamSerialNumber, uint pageNumber, PageFlags flags) { version = 0; this.flags = flags; absolute_granular_position = 0; stream_serial_number = streamSerialNumber; page_sequence_number = pageNumber; size = 0; data_size = 0; packet_sizes = new List <int>(); if (pageNumber == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { this.flags |= PageFlags.FirstPageOfStream; } }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { this.version = original.version; this.flags = flags; this.absolute_granular_position = original.absolute_granular_position; this.stream_serial_number = original.stream_serial_number; this.page_sequence_number = original.page_sequence_number + offset; this.size = original.size; this.data_size = original.data_size; this.packet_sizes = new List<int>(); if ((this.page_sequence_number == 0) && (((byte) (flags & PageFlags.FirstPacketContinued)) == 0)) { this.flags = (PageFlags) ((byte) (this.flags | PageFlags.FirstPageOfStream)); } }
public PageHeader(uint streamSerialNumber, uint pageNumber, PageFlags flags) { this.version = 0; this.flags = flags; this.absolute_granular_position = 0L; this.stream_serial_number = streamSerialNumber; this.page_sequence_number = pageNumber; this.size = 0; this.data_size = 0; this.packet_sizes = new List<int>(); if ((pageNumber == 0) && (((byte) (flags & PageFlags.FirstPacketContinued)) == 0)) { this.flags = (PageFlags) ((byte) (this.flags | PageFlags.FirstPageOfStream)); } }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; this.flags = flags; absolute_granular_position = original.absolute_granular_position; stream_serial_number = original.stream_serial_number; page_sequence_number = original.page_sequence_number + offset; size = original.size; data_size = original.data_size; packet_sizes = new List <int>(); if (page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { this.flags |= PageFlags.FirstPageOfStream; } }
public static unsafe ulong CalculatePageChecksum(byte *ptr, long pageNumber, PageFlags flags, int overflowSize) { var dataLength = Constants.Storage.PageSize - (PageHeader.ChecksumOffset + sizeof(ulong)); if ((flags & PageFlags.Overflow) == PageFlags.Overflow) { dataLength = overflowSize - (PageHeader.ChecksumOffset + sizeof(ulong)); } var ctx = Hashing.Streamed.XXHash64.BeginProcess((ulong)pageNumber); Hashing.Streamed.XXHash64.Process(ctx, ptr, PageHeader.ChecksumOffset); Hashing.Streamed.XXHash64.Process(ctx, ptr + PageHeader.ChecksumOffset + sizeof(ulong), dataLength); return(Hashing.Streamed.XXHash64.EndProcess(ctx)); }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> with a given serial number, page /// number, and flags. /// </summary> /// <param name="streamSerialNumber"> /// A <see cref="uint" /> value containing the serial number /// for the stream containing the page described by the new /// instance. /// </param> /// <param name="pageNumber"> /// A <see cref="uint" /> value containing the index of the /// page described by the new instance in the stream. /// </param> /// <param name="flags"> /// A <see cref="PageFlags" /> object containing the flags /// that apply to the page described by the new instance. /// </param> public PageHeader(uint streamSerialNumber, uint pageNumber, PageFlags flags) { version = 0; Flags = flags; absolute_granular_position = 0; StreamSerialNumber = streamSerialNumber; PageSequenceNumber = pageNumber; Size = 0; DataSize = 0; packet_sizes = new List <int> (); if (pageNumber == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { Flags |= PageFlags.FirstPageOfStream; } }
public PageHeader(PageHeader original, uint offset, PageFlags flags) { _version = original._version; _flags = flags; _absolute_granular_position = original._absolute_granular_position; _stream_serial_number = original._stream_serial_number; _page_sequence_number = original._page_sequence_number + offset; _size = original._size; _data_size = original._data_size; _packet_sizes = new List <int> (); if (_page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { _flags |= PageFlags.FirstPageOfStream; } }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> by copying the values from another /// instance, offsetting the page number and applying new /// flags. /// </summary> /// <param name="original"> /// A <see cref="PageHeader"/> object to copy the values /// from. /// </param> /// <param name="offset"> /// A <see cref="uint"/> value specifying how much to offset /// the page sequence number in the new instance. /// </param> /// <param name="flags"> /// A <see cref="PageFlags"/> value specifying the flags to /// use in the new instance. /// </param> public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; Flags = flags; absolute_granular_position = original.absolute_granular_position; StreamSerialNumber = original.StreamSerialNumber; PageSequenceNumber = original.PageSequenceNumber + offset; Size = original.Size; DataSize = original.DataSize; packet_sizes = new List <int> (); if (PageSequenceNumber == 0 && (flags & PageFlags.FirstPacketContinued) == 0) { Flags |= PageFlags.FirstPageOfStream; } }
public PageHeader(TagLib.Ogg.File file, long position) { if (file == null) { throw new ArgumentNullException("file"); } if ((position < 0L) || (position > (file.Length - 0x1bL))) { throw new ArgumentOutOfRangeException("position"); } file.Seek(position); ByteVector vector = file.ReadBlock(0x1b); if ((vector.Count < 0x1b) || !vector.StartsWith("OggS")) { throw new CorruptFileException("Error reading page header"); } this.version = vector[4]; this.flags = (PageFlags) vector[5]; this.absolute_granular_position = vector.Mid(6, 8).ToULong(false); this.stream_serial_number = vector.Mid(14, 4).ToUInt(false); this.page_sequence_number = vector.Mid(0x12, 4).ToUInt(false); int length = vector[0x1a]; ByteVector vector2 = file.ReadBlock(length); if ((length < 1) || (vector2.Count != length)) { throw new CorruptFileException("Incorrect number of page segments"); } this.size = (uint) (0x1b + length); this.packet_sizes = new List<int>(); int item = 0; this.data_size = 0; for (int i = 0; i < length; i++) { this.data_size += vector2[i]; item += vector2[i]; if (vector2[i] < 0xff) { this.packet_sizes.Add(item); item = 0; } } if (item > 0) { this.packet_sizes.Add(item); } }
public override void Map(uint pAddr, uint vAddr, PageFlags flags, UpdateUsedPagesFlags UpdateUsedPages = UpdateUsedPagesFlags.Both) { PTEFlags pteFlags = PTEFlags.None; if ((flags & PageFlags.Present) != 0) { pteFlags |= PTEFlags.Present; } if ((flags & PageFlags.KernelOnly) == 0) { pteFlags |= PTEFlags.UserAllowed; } if ((flags & PageFlags.Writeable) != 0) { pteFlags |= PTEFlags.Writeable; } Map(pAddr, vAddr, pteFlags, UpdateUsedPages); }
/// <summary> /// Allocates a virtual address range /// </summary> /// <param name="size">The size</param> /// <returns>The pointer to the block</returns> public static void *AllocateVirtual(int size) { // Page align size uint sizeAligned = AlignUp((uint)size); // Allocate int free = bitmap.FindFirstFreeRange((int)(sizeAligned / 0x1000), true); int start = free * 0x1000; int end = (int)(start + sizeAligned); PageFlags flags = PageFlags.Present | PageFlags.Writable | PageFlags.UserMode; for (int address = start; address < end; address += 0x1000) { int phys = (int)PhysicalMemoryManager.Alloc(); MapPage(KernelDirectory, phys, address, flags); MapPage(CurrentDirectory, phys, address, flags); } // Clear the data before returning it for safety Memory.Memclear((void *)start, size); return((void *)start); }
/// <summary> /// Maps the specified virtual address to the specified physical address. /// </summary> /// <param name="pAddr">The physical address to map to.</param> /// <param name="vAddr">The virtual address to map.</param> /// <param name="flags">The flags to apply to the allocated pages.</param> /// <param name="UpdateUsedPages">Which, if any, of the physical and virtual used pages lists to update.</param> public abstract void Map(uint pAddr, uint vAddr, PageFlags flags, UpdateUsedPagesFlags UpdateUsedPages = UpdateUsedPagesFlags.Both);
public PageHeader (PageHeader original, uint offset, PageFlags flags) { _version = original._version; _flags = flags; _absolute_granular_position = original._absolute_granular_position; _stream_serial_number = original._stream_serial_number; _page_sequence_number = original._page_sequence_number + offset; _size = original._size; _data_size = original._data_size; _packet_sizes = new List<int> (); if (_page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) _flags |= PageFlags.FirstPageOfStream; }
internal Page AllocatePage(int numberOfPages, PageFlags flags, long? pageNumber = null) { if (_disposed) throw new ObjectDisposedException("Transaction"); if (pageNumber == null) { pageNumber = _freeSpaceHandling.TryAllocateFromFreeSpace(this, numberOfPages); if (pageNumber == null) // allocate from end of file { pageNumber = State.NextPageNumber; State.NextPageNumber += numberOfPages; } } if (_env.Options.MaxStorageSize.HasValue) // check against quota { var maxAvailablePageNumber = _env.Options.MaxStorageSize / AbstractPager.PageSize; if(pageNumber.Value > maxAvailablePageNumber) throw new QuotaException( string.Format( "The maximum storage size quota ({0} bytes) has been reached. " + "Currently configured storage quota is allowing to allocate the following maximum page number {1}, while the requested page number is {2}. " + "To increase the quota, use the MaxStorageSize property on the storage environment options.", _env.Options.MaxStorageSize, maxAvailablePageNumber, pageNumber.Value)); } Debug.Assert(pageNumber < State.NextPageNumber); var pageFromScratchBuffer = _env.ScratchBufferPool.Allocate(this, numberOfPages); _transactionPages.Add(pageFromScratchBuffer); var page = _env.ScratchBufferPool.ReadPage(pageFromScratchBuffer.ScratchFileNumber, pageFromScratchBuffer.PositionInScratchBuffer); page.PageNumber = pageNumber.Value; _allocatedPagesInTransaction++; if (numberOfPages > 1) { _overflowPagesInTransaction += (numberOfPages - 1); } _scratchPagesTable[pageNumber.Value] = pageFromScratchBuffer; page.Lower = (ushort)Constants.PageHeaderSize; page.Flags = flags; if ((flags & PageFlags.KeysPrefixed) == PageFlags.KeysPrefixed) { page.Upper = (ushort) (AbstractPager.PageSize - Constants.PrefixInfoSectionSize); page.ClearPrefixInfo(); } else page.Upper = AbstractPager.PageSize; page.Dirty = true; _dirtyPages.Add(page.PageNumber); if (numberOfPages > 1) _dirtyOverflowPages.Add(page.PageNumber + 1, numberOfPages - 1); return page; }
bool ReadPageHeader(out int streamSerial, out PageFlags flags, out long granulePosition, out int seqNo, out long dataOffset, out int[] packetSizes, out bool lastPacketContinues) { streamSerial = -1; flags = PageFlags.None; granulePosition = -1L; seqNo = -1; dataOffset = -1L; packetSizes = null; lastPacketContinues = false; // header var hdrBuf = new byte[27]; if (_stream.Read(hdrBuf, 0, hdrBuf.Length) != hdrBuf.Length) return false; // capture signature if (hdrBuf[0] != 0x4f || hdrBuf[1] != 0x67 || hdrBuf[2] != 0x67 || hdrBuf[3] != 0x53) return false; // check the stream version if (hdrBuf[4] != 0) return false; // bit flags flags = (PageFlags)hdrBuf[5]; // granulePosition granulePosition = BitConverter.ToInt64(hdrBuf, 6); // stream serial streamSerial = BitConverter.ToInt32(hdrBuf, 14); // sequence number seqNo = BitConverter.ToInt32(hdrBuf, 18); // save off the CRC var crc = BitConverter.ToUInt32(hdrBuf, 22); // start calculating the CRC value for this page var testCRC = 0U; for (int i = 0; i < 22; i++) { UpdateCRC(hdrBuf[i], ref testCRC); } UpdateCRC(0, ref testCRC); UpdateCRC(0, ref testCRC); UpdateCRC(0, ref testCRC); UpdateCRC(0, ref testCRC); UpdateCRC(hdrBuf[26], ref testCRC); // figure out the length of the page var segCnt = (int)hdrBuf[26]; packetSizes = new int[segCnt]; int size = 0, idx = 0; for (int i = 0; i < segCnt; i++) { var temp = _stream.ReadByte(); UpdateCRC(temp, ref testCRC); packetSizes[idx] += temp; if (temp < 255) { ++idx; lastPacketContinues = false; } else { lastPacketContinues = true; } size += temp; } if (lastPacketContinues) ++idx; if (idx < packetSizes.Length) { var temp = new int[idx]; for (int i = 0; i < idx; i++) { temp[i] = packetSizes[i]; } packetSizes = temp; } dataOffset = _stream.Position; // now we have to go through every byte in the page while (--size >= 0) { UpdateCRC(_stream.ReadByte(), ref testCRC); } _nextPageOffset = _stream.Position; _containerBits += 8 * (27 + segCnt); if (testCRC == crc) { ++_pageCount; return true; } _containerBits -= 8 * (27 + segCnt); // we're going to look for the bits separately... return false; }
internal Page AllocatePage(int numberOfPages, PageFlags flags, long?pageNumber = null) { if (pageNumber == null) { pageNumber = _freeSpaceHandling.TryAllocateFromFreeSpace(this, numberOfPages); if (pageNumber == null) // allocate from end of file { pageNumber = State.NextPageNumber; State.NextPageNumber += numberOfPages; } } if (_env.Options.MaxStorageSize.HasValue) // check against quota { var maxAvailablePageNumber = _env.Options.MaxStorageSize / AbstractPager.PageSize; if (pageNumber.Value > maxAvailablePageNumber) { throw new QuotaException( string.Format( "The maximum storage size quota ({0} bytes) has been reached. " + "Currently configured storage quota is allowing to allocate the following maximum page number {1}, while the requested page number is {2}. " + "To increase the quota, use the MaxStorageSize property on the storage environment options.", _env.Options.MaxStorageSize, maxAvailablePageNumber, pageNumber.Value)); } } Debug.Assert(pageNumber < State.NextPageNumber); var pageFromScratchBuffer = _env.ScratchBufferPool.Allocate(this, numberOfPages); _transactionPages.Add(pageFromScratchBuffer); var page = _env.ScratchBufferPool.ReadPage(pageFromScratchBuffer.ScratchFileNumber, pageFromScratchBuffer.PositionInScratchBuffer); page.PageNumber = pageNumber.Value; _allocatedPagesInTransaction++; if (numberOfPages > 1) { _overflowPagesInTransaction += (numberOfPages - 1); } _scratchPagesTable[pageNumber.Value] = pageFromScratchBuffer; page.Lower = (ushort)Constants.PageHeaderSize; page.Flags = flags; if ((flags & PageFlags.KeysPrefixed) == PageFlags.KeysPrefixed) { page.Upper = (ushort)(AbstractPager.PageSize - Constants.PrefixInfoSectionSize); page.ClearPrefixInfo(); } else { page.Upper = AbstractPager.PageSize; } page.Dirty = true; _dirtyPages.Add(page.PageNumber); if (numberOfPages > 1) { _dirtyOverflowPages.Add(page.PageNumber + 1, numberOfPages - 1); } return(page); }
/// <summary> /// Maps a physical address (range) to a free virtual address (range) /// </summary> /// <param name="directory">The page directory</param> /// <param name="phys">The physical address</param> /// <param name="size">The size of the range</param> /// <param name="flags">The flags</param> /// <returns>The virtual address</returns> public static void *MapToVirtual(PageDirectory *directory, int phys, int size, PageFlags flags) { int sizeAligned = (int)AlignUp((uint)size) / 0x1000; int free = bitmap.FindFirstFreeRange(sizeAligned, true); int virt = free * 0x1000; for (int i = 0; i < sizeAligned; i++) { int offset = i * 0x1000; MapPage(directory, phys + offset, virt + offset, flags); PhysicalMemoryManager.Set(phys + offset); } Paging.setDirectoryInternal(Paging.CurrentDirectoryPhysical); return((void *)virt); }
internal static Page NewPage(Transaction tx, PageFlags flags, int num) { var page = tx.AllocatePage(num); page.Flags = flags; return page; }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> by copying the values from another /// instance, offsetting the page number and applying new /// flags. /// </summary> /// <param name="original"> /// A <see cref="PageHeader"/> object to copy the values /// from. /// </param> /// <param name="offset"> /// A <see cref="uint"/> value specifying how much to offset /// the page sequence number in the new instance. /// </param> /// <param name="flags"> /// A <see cref="PageFlags"/> value specifying the flags to /// use in the new instance. /// </param> public PageHeader(PageHeader original, uint offset, PageFlags flags) { version = original.version; this.flags = flags; absolute_granular_position = original.absolute_granular_position; stream_serial_number = original.stream_serial_number; page_sequence_number = original.page_sequence_number + offset; size = original.size; data_size = original.data_size; packet_sizes = new List<int> (); if (page_sequence_number == 0 && (flags & PageFlags.FirstPacketContinued) == 0) this.flags |= PageFlags.FirstPageOfStream; }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="PageHeader" /> by reading a raw Ogg page header /// from a specified position in a specified file. /// </summary> /// <param name="file"> /// A <see cref="File" /> object containing the file from /// which the contents of the new instance are to be read. /// </param> /// <param name="position"> /// A <see cref="long" /> value specify at what position to /// read. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="file" /> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="position" /> is less than zero or greater /// than the size of the file. /// </exception> /// <exception cref="CorruptFileException"> /// The Ogg identifier could not be found at the correct /// location. /// </exception> public PageHeader(File file, long position) { if (file == null) throw new ArgumentNullException ("file"); if (position < 0 || position > file.Length - 27) throw new ArgumentOutOfRangeException ( "position"); file.Seek (position); // An Ogg page header is at least 27 bytes, so we'll go // ahead and read that much and then get the rest when // we're ready for it. ByteVector data = file.ReadBlock (27); if (data.Count < 27 || !data.StartsWith ("OggS")) System.Console.WriteLine( "Error reading page header"); version = data [4]; this.flags = (PageFlags) data [5]; absolute_granular_position = data.Mid(6, 8).ToULong ( false); stream_serial_number = data.Mid(14, 4).ToUInt (false); page_sequence_number = data.Mid(18, 4).ToUInt (false); // Byte number 27 is the number of page segments, which // is the only variable length portion of the page // header. After reading the number of page segments // we'll then read in the coresponding data for this // count. int page_segment_count = data [26]; ByteVector page_segments = file.ReadBlock (page_segment_count); // Another sanity check. if (page_segment_count < 1 || page_segments.Count != page_segment_count) System.Console.WriteLine( "Incorrect number of page segments"); // The base size of an Ogg page 27 bytes plus the number // of lacing values. size = (uint)(27 + page_segment_count); packet_sizes = new List<int> (); int packet_size = 0; data_size = 0; for (int i = 0; i < page_segment_count; i++) { data_size += page_segments [i]; packet_size += page_segments [i]; if (page_segments [i] < 255) { packet_sizes.Add (packet_size); packet_size = 0; } } if (packet_size > 0) packet_sizes.Add (packet_size); }