mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.5 KiB
146 lines
3.5 KiB
//----------------------------------------------------------------------------- |
|
// |
|
// Copyright (C) Microsoft Corporation. All Rights Reserved. |
|
// |
|
//----------------------------------------------------------------------------- |
|
using System; |
|
using System.IO; |
|
|
|
namespace Microsoft.Cci.Pdb { |
|
internal class DataStream { |
|
internal DataStream() { |
|
this.contentSize = 0; |
|
this.pages = null; |
|
} |
|
|
|
internal DataStream(int contentSize, BitAccess bits, int count) { |
|
this.contentSize = contentSize; |
|
if (count > 0) { |
|
this.pages = new int[count]; |
|
bits.ReadInt32(this.pages); |
|
} |
|
} |
|
|
|
internal void Read(PdbReader reader, BitAccess bits) { |
|
bits.MinCapacity(contentSize); |
|
Read(reader, 0, bits.Buffer, 0, contentSize); |
|
} |
|
|
|
internal void Read(PdbReader reader, int position, |
|
byte[] bytes, int offset, int data) { |
|
if (position + data > contentSize) { |
|
throw new PdbException("DataStream can't read off end of stream. " + |
|
"(pos={0},siz={1})", |
|
position, data); |
|
} |
|
if (position == contentSize) { |
|
return; |
|
} |
|
|
|
int left = data; |
|
int page = position / reader.pageSize; |
|
int rema = position % reader.pageSize; |
|
|
|
// First get remained of first page. |
|
if (rema != 0) { |
|
int todo = reader.pageSize - rema; |
|
if (todo > left) { |
|
todo = left; |
|
} |
|
|
|
reader.Seek(pages[page], rema); |
|
reader.Read(bytes, offset, todo); |
|
|
|
offset += todo; |
|
left -= todo; |
|
page++; |
|
} |
|
|
|
// Now get the remaining pages. |
|
while (left > 0) { |
|
int todo = reader.pageSize; |
|
if (todo > left) { |
|
todo = left; |
|
} |
|
|
|
reader.Seek(pages[page], 0); |
|
reader.Read(bytes, offset, todo); |
|
|
|
offset += todo; |
|
left -= todo; |
|
page++; |
|
} |
|
} |
|
|
|
internal void Write(PdbWriter writer, byte[] bytes) { |
|
Write(writer, bytes, bytes.Length); |
|
} |
|
|
|
internal void Write(PdbWriter writer, byte[] bytes, int data) { |
|
if (bytes == null || data == 0) { |
|
return; |
|
} |
|
|
|
int left = data; |
|
int used = 0; |
|
int rema = contentSize % writer.pageSize; |
|
if (rema != 0) { |
|
int todo = writer.pageSize - rema; |
|
if (todo > left) { |
|
todo = left; |
|
} |
|
|
|
int lastPage = pages[pages.Length - 1]; |
|
writer.Seek(lastPage, rema); |
|
writer.Write(bytes, used, todo); |
|
used += todo; |
|
left -= todo; |
|
} |
|
|
|
if (left > 0) { |
|
int count = (left + writer.pageSize - 1) / writer.pageSize; |
|
int page0 = writer.AllocatePages(count); |
|
|
|
writer.Seek(page0, 0); |
|
writer.Write(bytes, used, left); |
|
|
|
AddPages(page0, count); |
|
} |
|
|
|
contentSize += data; |
|
} |
|
|
|
private void AddPages(int page0, int count) { |
|
if (pages == null) { |
|
pages = new int[count]; |
|
for (int i = 0; i < count; i++) { |
|
pages[i] = page0 + i; |
|
} |
|
} else { |
|
int[] old = pages; |
|
int used = old.Length; |
|
|
|
pages = new int[used + count]; |
|
Array.Copy(old, pages, used); |
|
for (int i = 0; i < count; i++) { |
|
pages[used + i] = page0 + i; |
|
} |
|
} |
|
} |
|
|
|
internal int Pages { |
|
get { return pages == null ? 0 : pages.Length; } |
|
} |
|
|
|
internal int Length { |
|
get { return contentSize; } |
|
} |
|
|
|
internal int GetPage(int index) { |
|
return pages[index]; |
|
} |
|
|
|
internal int contentSize; |
|
internal int[] pages; |
|
} |
|
}
|
|
|