2 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
7 using System
.Collections
;
9 namespace Mono
.PEToolkit
.Metadata
{
12 /// Metadata tables heap (#~).
15 /// Partition II; Chapter 21 & 23.1.6
17 public class TablesHeap
: TablesHeapBase
{
19 private long valid
; // bitvector of valid tables
20 //(64-bit, max index = TableId.MAX)
21 private int numTabs
; // number of tables (calculated from valid)
23 private long sorted
; // bitvector of sorted tables (64-bit)
25 // schema version (currently 1.0)
29 // bitvector for heap-size flags:
30 // bit 1 - if set #Strings heap uses wide indices (dword)
31 // bit 2 - if set #GUID heap uses wide indices
32 // bit 3 - if set #Blob heap uses wide indices
33 // otherwise (particular bit is not set) index size is word.
34 private byte heapSizes
;
37 private Hashtable tables
;
40 internal TablesHeap (MDStream stream
) : base (stream
)
46 /// Gets or sets bitvector of valid tables (64-bit).
48 public override long Valid
{
58 /// Gets or sets bitvector of sorted tables (64-bit).
60 public override long Sorted
{
71 // "Universal" accessors for Valid and Sorted bitvectors.
75 public bool IsValid (TableId tab
)
77 return (valid
& (1L << (int) tab
)) != 0;
80 public void SetValid (TableId tab
, bool b
)
82 long mask
= 1L << (int) tab
;
92 /// True if the given table in this heap is sorted.
94 /// <param name="tab"></param>
95 /// <returns></returns>
96 public bool IsSorted (TableId tab
)
98 return (sorted
& (1L << (int) tab
)) != 0;
102 /// Marks specified table in this heap as sorted or unsorted.
104 /// <param name="tab"></param>
105 /// <param name="b"></param>
106 public void SetSorted (TableId tab
, bool b
)
108 long mask
= 1L << (int) tab
;
118 public byte HeapSizes
{
127 public int StringsIndexSize
{
129 return 2 + ((heapSizes
& 1) << 1);
133 public int GUIDIndexSize
{
135 return 2 + (heapSizes
& 2);
139 public int BlobIndexSize
{
141 return 2 + ((heapSizes
& 4) >> 1);
147 unsafe override public void FromRawData (byte [] rawData
)
152 if (rawData
== null || rawData
.Length
< 24) {
153 throw new BadMetaDataException ("Invalid header for #~ heap.");
156 verMaj
= rawData
[4];
157 verMin
= rawData
[5];
158 heapSizes
= rawData
[6];
160 valid
= LEBitConverter
.ToInt64 (rawData
, 8);
161 sorted
= LEBitConverter
.ToInt64 (rawData
, 16);
163 // Calc number of tables from valid bitvector.
165 for (int i
= (int) TableId
.Count
; --i
>= 0;) {
166 numTabs
+= (int) (valid
>> i
) & 1;
169 int [] rows
= new int [(int) TableId
.Count
];
170 Array
.Clear (rows
, 0, rows
.Length
);
171 int offs
= 24; // offset to #~::Rows
172 for (int i
= 0; i
< numTabs
; i
++) {
176 while (n
< i
&& v
!= 0) {
182 rows
[vpos
] = LEBitConverter
.ToInt32 (rawData
, offs
);
183 offs
+= sizeof (int);
187 // TODO: this could be called from constructor
188 // This sequence: MDHeap::.ctor -> FromRawData -> RegisterTable
189 // and we are making "this" available here, before the object
190 // is fully constructed. This is bad, fix it somehow.
191 TabsDecoder
.DecodePhysicalTables (this, rawData
, offs
, rows
);
196 public void RegisterTable (MDTable tab
)
198 if (tables
== null) tables
= new Hashtable (64);
199 tables
[tab
.Id
] = tab
;
202 public MDTable
this [TableId id
] {
204 return tables
[id
] as MDTable
;
208 public ICollection Tables
{
210 return tables
.Values
;