1 //-----------------------------------------------------------------------------
3 // Copyright (C) Microsoft Corporation. All Rights Reserved.
5 //-----------------------------------------------------------------------------
9 namespace Microsoft.Cci.Pdb {
10 internal class PdbWriter {
11 internal PdbWriter(Stream writer, int pageSize) {
12 this.pageSize = pageSize;
13 this.usedBytes = pageSize * 3;
16 writer.SetLength(usedBytes);
19 internal void WriteMeta(DataStream[] streams, BitAccess bits) {
20 PdbFileHeader head = new PdbFileHeader(pageSize);
22 WriteDirectory(streams,
23 out head.directoryRoot,
24 out head.directorySize,
29 head.pagesUsed = usedBytes / pageSize;
31 writer.Seek(0, SeekOrigin.Begin);
32 head.Write(writer, bits);
35 private void WriteDirectory(DataStream[] streams,
36 out int directoryRoot,
37 out int directorySize,
39 DataStream directory = new DataStream();
42 for (int s = 0; s < streams.Length; s++) {
43 if (streams[s].Length > 0) {
44 pages += streams[s].Pages;
48 int use = 4 * (1 + streams.Length + pages);
49 bits.MinCapacity(use);
50 bits.WriteInt32(streams.Length);
51 for (int s = 0; s < streams.Length; s++) {
52 bits.WriteInt32(streams[s].Length);
54 for (int s = 0; s < streams.Length; s++) {
55 if (streams[s].Length > 0) {
56 bits.WriteInt32(streams[s].pages);
59 directory.Write(this, bits.Buffer, use);
60 directorySize = directory.Length;
62 use = 4 * directory.Pages;
63 bits.MinCapacity(use);
64 bits.WriteInt32(directory.pages);
66 DataStream ddir = new DataStream();
67 ddir.Write(this, bits.Buffer, use);
69 directoryRoot = ddir.pages[0];
72 private void WriteFreeMap() {
73 byte[] buffer = new byte[pageSize];
75 // We configure the old free map with only the first 3 pages allocated.
77 for (int i = 1; i < pageSize; i++) {
81 Write(buffer, 0, pageSize);
83 // We configure the new free map with all of the used pages gone.
84 int count = usedBytes / pageSize;
86 for (int i = 0; i < full; i++) {
90 buffer[full] = (byte)(0xff << rema);
93 Write(buffer, 0, pageSize);
96 internal int AllocatePages(int count) {
97 int begin = usedBytes;
99 usedBytes += count * pageSize;
100 writer.SetLength(usedBytes);
102 if (usedBytes > pageSize * pageSize * 8) {
103 throw new Exception("PdbWriter does not support multiple free maps.");
105 return begin / pageSize;
108 internal void Seek(int page, int offset) {
109 writer.Seek(page * pageSize + offset, SeekOrigin.Begin);
112 internal void Write(byte[] bytes, int offset, int count) {
113 writer.Write(bytes, offset, count);
116 //////////////////////////////////////////////////////////////////////
118 internal int PageSize {
119 get { return pageSize; }
122 //////////////////////////////////////////////////////////////////////
124 internal readonly int pageSize;
125 private Stream writer;
126 private int usedBytes;