a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
147 lines
3.5 KiB
C#
147 lines
3.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
}
|