Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.cs
[mono.git] / mcs / class / IKVM.Reflection / Metadata / Tables.cs
1 /*
2   Copyright (C) 2009-2012 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Text;
27 using IKVM.Reflection.Emit;
28 using IKVM.Reflection.Writer;
29 using IKVM.Reflection.Reader;
30
31 namespace IKVM.Reflection.Metadata
32 {
33         internal abstract class Table
34         {
35                 internal bool Sorted;
36
37                 internal bool IsBig
38                 {
39                         get { return RowCount > 65535; }
40                 }
41
42                 internal abstract int RowCount { get; set; }
43
44                 internal abstract void Write(MetadataWriter mw);
45                 internal abstract void Read(MetadataReader mr);
46
47                 internal int GetLength(MetadataWriter md)
48                 {
49                         return RowCount * GetRowSize(new RowSizeCalc(md));
50                 }
51
52                 protected abstract int GetRowSize(RowSizeCalc rsc);
53
54                 protected sealed class RowSizeCalc
55                 {
56                         private readonly MetadataWriter mw;
57                         private int size;
58
59                         internal RowSizeCalc(MetadataWriter mw)
60                         {
61                                 this.mw = mw;
62                         }
63
64                         internal RowSizeCalc AddFixed(int size)
65                         {
66                                 this.size += size;
67                                 return this;
68                         }
69
70                         internal RowSizeCalc WriteStringIndex()
71                         {
72                                 if (mw.bigStrings)
73                                 {
74                                         this.size += 4;
75                                 }
76                                 else
77                                 {
78                                         this.size += 2;
79                                 }
80                                 return this;
81                         }
82
83                         internal RowSizeCalc WriteGuidIndex()
84                         {
85                                 if (mw.bigGuids)
86                                 {
87                                         this.size += 4;
88                                 }
89                                 else
90                                 {
91                                         this.size += 2;
92                                 }
93                                 return this;
94                         }
95
96                         internal RowSizeCalc WriteBlobIndex()
97                         {
98                                 if (mw.bigBlobs)
99                                 {
100                                         this.size += 4;
101                                 }
102                                 else
103                                 {
104                                         this.size += 2;
105                                 }
106                                 return this;
107                         }
108
109                         internal RowSizeCalc WriteTypeDefOrRef()
110                         {
111                                 if (mw.bigTypeDefOrRef)
112                                 {
113                                         this.size += 4;
114                                 }
115                                 else
116                                 {
117                                         this.size += 2;
118                                 }
119                                 return this;
120                         }
121
122                         internal RowSizeCalc WriteField()
123                         {
124                                 if (mw.bigField)
125                                 {
126                                         size += 4;
127                                 }
128                                 else
129                                 {
130                                         size += 2;
131                                 }
132                                 return this;
133                         }
134
135                         internal RowSizeCalc WriteMethodDef()
136                         {
137                                 if (mw.bigMethodDef)
138                                 {
139                                         this.size += 4;
140                                 }
141                                 else
142                                 {
143                                         this.size += 2;
144                                 }
145                                 return this;
146                         }
147
148                         internal RowSizeCalc WriteParam()
149                         {
150                                 if (mw.bigParam)
151                                 {
152                                         this.size += 4;
153                                 }
154                                 else
155                                 {
156                                         this.size += 2;
157                                 }
158                                 return this;
159                         }
160
161                         internal RowSizeCalc WriteResolutionScope()
162                         {
163                                 if (mw.bigResolutionScope)
164                                 {
165                                         this.size += 4;
166                                 }
167                                 else
168                                 {
169                                         this.size += 2;
170                                 }
171                                 return this;
172                         }
173
174                         internal RowSizeCalc WriteMemberRefParent()
175                         {
176                                 if (mw.bigMemberRefParent)
177                                 {
178                                         this.size += 4;
179                                 }
180                                 else
181                                 {
182                                         this.size += 2;
183                                 }
184                                 return this;
185                         }
186
187                         internal RowSizeCalc WriteHasCustomAttribute()
188                         {
189                                 if (mw.bigHasCustomAttribute)
190                                 {
191                                         size += 4;
192                                 }
193                                 else
194                                 {
195                                         size += 2;
196                                 }
197                                 return this;
198                         }
199
200                         internal RowSizeCalc WriteCustomAttributeType()
201                         {
202                                 if (mw.bigCustomAttributeType)
203                                 {
204                                         this.size += 4;
205                                 }
206                                 else
207                                 {
208                                         this.size += 2;
209                                 }
210                                 return this;
211                         }
212
213                         internal RowSizeCalc WriteHasConstant()
214                         {
215                                 if (mw.bigHasConstant)
216                                 {
217                                         size += 4;
218                                 }
219                                 else
220                                 {
221                                         size += 2;
222                                 }
223                                 return this;
224                         }
225
226                         internal RowSizeCalc WriteTypeDef()
227                         {
228                                 if (mw.bigTypeDef)
229                                 {
230                                         this.size += 4;
231                                 }
232                                 else
233                                 {
234                                         this.size += 2;
235                                 }
236                                 return this;
237                         }
238
239                         internal RowSizeCalc WriteMethodDefOrRef()
240                         {
241                                 if (mw.bigMethodDefOrRef)
242                                 {
243                                         this.size += 4;
244                                 }
245                                 else
246                                 {
247                                         this.size += 2;
248                                 }
249                                 return this;
250                         }
251
252                         internal RowSizeCalc WriteEvent()
253                         {
254                                 if (mw.bigEvent)
255                                 {
256                                         this.size += 4;
257                                 }
258                                 else
259                                 {
260                                         this.size += 2;
261                                 }
262                                 return this;
263                         }
264
265                         internal RowSizeCalc WriteProperty()
266                         {
267                                 if (mw.bigProperty)
268                                 {
269                                         this.size += 4;
270                                 }
271                                 else
272                                 {
273                                         this.size += 2;
274                                 }
275                                 return this;
276                         }
277
278                         internal RowSizeCalc WriteHasSemantics()
279                         {
280                                 if (mw.bigHasSemantics)
281                                 {
282                                         this.size += 4;
283                                 }
284                                 else
285                                 {
286                                         this.size += 2;
287                                 }
288                                 return this;
289                         }
290
291                         internal RowSizeCalc WriteImplementation()
292                         {
293                                 if (mw.bigImplementation)
294                                 {
295                                         this.size += 4;
296                                 }
297                                 else
298                                 {
299                                         this.size += 2;
300                                 }
301                                 return this;
302                         }
303
304                         internal RowSizeCalc WriteTypeOrMethodDef()
305                         {
306                                 if (mw.bigTypeOrMethodDef)
307                                 {
308                                         this.size += 4;
309                                 }
310                                 else
311                                 {
312                                         this.size += 2;
313                                 }
314                                 return this;
315                         }
316
317                         internal RowSizeCalc WriteGenericParam()
318                         {
319                                 if (mw.bigGenericParam)
320                                 {
321                                         this.size += 4;
322                                 }
323                                 else
324                                 {
325                                         this.size += 2;
326                                 }
327                                 return this;
328                         }
329
330                         internal RowSizeCalc WriteHasDeclSecurity()
331                         {
332                                 if (mw.bigHasDeclSecurity)
333                                 {
334                                         this.size += 4;
335                                 }
336                                 else
337                                 {
338                                         this.size += 2;
339                                 }
340                                 return this;
341                         }
342
343                         internal RowSizeCalc WriteMemberForwarded()
344                         {
345                                 if (mw.bigMemberForwarded)
346                                 {
347                                         this.size += 4;
348                                 }
349                                 else
350                                 {
351                                         this.size += 2;
352                                 }
353                                 return this;
354                         }
355
356                         internal RowSizeCalc WriteModuleRef()
357                         {
358                                 if (mw.bigModuleRef)
359                                 {
360                                         this.size += 4;
361                                 }
362                                 else
363                                 {
364                                         this.size += 2;
365                                 }
366                                 return this;
367                         }
368
369                         internal RowSizeCalc WriteHasFieldMarshal()
370                         {
371                                 if (mw.bigHasFieldMarshal)
372                                 {
373                                         this.size += 4;
374                                 }
375                                 else
376                                 {
377                                         this.size += 2;
378                                 }
379                                 return this;
380                         }
381
382                         internal int Value
383                         {
384                                 get { return size; }
385                         }
386                 }
387         }
388
389         abstract class Table<T> : Table
390         {
391                 internal T[] records = new T[1];
392                 protected int rowCount;
393
394                 internal sealed override int RowCount
395                 {
396                         get { return rowCount; }
397                         set { rowCount = value; records = new T[value]; }
398                 }
399
400                 protected override int GetRowSize(RowSizeCalc rsc)
401                 {
402                         throw new InvalidOperationException();
403                 }
404
405                 internal int AddRecord(T newRecord)
406                 {
407                         if (rowCount == records.Length)
408                         {
409                                 T[] newarr = new T[records.Length * 2];
410                                 Array.Copy(records, newarr, records.Length);
411                                 records = newarr;
412                         }
413                         records[rowCount++] = newRecord;
414                         return rowCount;
415                 }
416
417                 internal int AddVirtualRecord()
418                 {
419                         return ++rowCount;
420                 }
421
422                 internal override void Write(MetadataWriter mw)
423                 {
424                         throw new InvalidOperationException();
425                 }
426         }
427
428         abstract class SortedTable<T> : Table<T>, IComparer<int>
429                 where T : SortedTable<T>.ISortKey
430         {
431                 internal interface ISortKey
432                 {
433                         int Key { get; }
434                 }
435
436                 internal struct Enumerable
437                 {
438                         private readonly SortedTable<T> table;
439                         private readonly int token;
440
441                         internal Enumerable(SortedTable<T> table, int token)
442                         {
443                                 this.table = table;
444                                 this.token = token;
445                         }
446
447                         public Enumerator GetEnumerator()
448                         {
449                                 T[] records = table.records;
450                                 if (!table.Sorted)
451                                 {
452                                         return new Enumerator(records, table.RowCount - 1, -1, token);
453                                 }
454                                 int index = BinarySearch(records, table.RowCount, token & 0xFFFFFF);
455                                 if (index < 0)
456                                 {
457                                         return new Enumerator(null, 0, 1, -1);
458                                 }
459                                 int start = index;
460                                 while (start > 0 && (records[start - 1].Key & 0xFFFFFF) == (token & 0xFFFFFF))
461                                 {
462                                         start--;
463                                 }
464                                 int end = index;
465                                 int max = table.RowCount - 1;
466                                 while (end < max && (records[end + 1].Key & 0xFFFFFF) == (token & 0xFFFFFF))
467                                 {
468                                         end++;
469                                 }
470                                 return new Enumerator(records, end, start - 1, token);
471                         }
472
473                         private static int BinarySearch(T[] records, int length, int maskedToken)
474                         {
475                                 int min = 0;
476                                 int max = length - 1;
477                                 while (min <= max)
478                                 {
479                                         int mid = min + ((max - min) / 2);
480                                         int maskedValue = records[mid].Key & 0xFFFFFF;
481                                         if (maskedToken == maskedValue)
482                                         {
483                                                 return mid;
484                                         }
485                                         else if (maskedToken < maskedValue)
486                                         {
487                                                 max = mid - 1;
488                                         }
489                                         else
490                                         {
491                                                 min = mid + 1;
492                                         }
493                                 }
494                                 return -1;
495                         }
496                 }
497
498                 internal struct Enumerator
499                 {
500                         private readonly T[] records;
501                         private readonly int token;
502                         private readonly int max;
503                         private int index;
504
505                         internal Enumerator(T[] records, int max, int index, int token)
506                         {
507                                 this.records = records;
508                                 this.token = token;
509                                 this.max = max;
510                                 this.index = index;
511                         }
512
513                         public int Current
514                         {
515                                 get { return index; }
516                         }
517
518                         public bool MoveNext()
519                         {
520                                 while (index < max)
521                                 {
522                                         index++;
523                                         if (records[index].Key == token)
524                                         {
525                                                 return true;
526                                         }
527                                 }
528                                 return false;
529                         }
530                 }
531
532                 internal Enumerable Filter(int token)
533                 {
534                         return new Enumerable(this, token);
535                 }
536
537                 protected void Sort()
538                 {
539                         int[] map = new int[rowCount];
540                         for (int i = 0; i < map.Length; i++)
541                         {
542                                 map[i] = i;
543                         }
544                         Array.Sort(map, this);
545                         T[] newRecords = new T[rowCount];
546                         for (int i = 0; i < map.Length; i++)
547                         {
548                                 newRecords[i] = records[map[i]];
549                         }
550                         records = newRecords;
551                 }
552
553                 int IComparer<int>.Compare(int x, int y)
554                 {
555                         int rc = records[x].Key.CompareTo(records[y].Key);
556                         return rc == 0 ? x.CompareTo(y) : rc;
557                 }
558         }
559
560         sealed class ModuleTable : Table<ModuleTable.Record>
561         {
562                 internal const int Index = 0x00;
563
564                 internal struct Record
565                 {
566                         internal short Generation;
567                         internal int Name; // -> StringHeap
568                         internal int Mvid; // -> GuidHeap
569                         internal int EncId; // -> GuidHeap
570                         internal int EncBaseId; // -> GuidHeap
571                 }
572
573                 internal override void Read(MetadataReader mr)
574                 {
575                         for (int i = 0; i < records.Length; i++)
576                         {
577                                 records[i].Generation = mr.ReadInt16();
578                                 records[i].Name = mr.ReadStringIndex();
579                                 records[i].Mvid = mr.ReadGuidIndex();
580                                 records[i].EncId = mr.ReadGuidIndex();
581                                 records[i].EncBaseId = mr.ReadGuidIndex();
582                         }
583                 }
584
585                 internal override void Write(MetadataWriter mw)
586                 {
587                         for (int i = 0; i < rowCount; i++)
588                         {
589                                 mw.Write(records[i].Generation);
590                                 mw.WriteStringIndex(records[i].Name);
591                                 mw.WriteGuidIndex(records[i].Mvid);
592                                 mw.WriteGuidIndex(records[i].EncId);
593                                 mw.WriteGuidIndex(records[i].EncBaseId);
594                         }
595                 }
596
597                 protected override int GetRowSize(RowSizeCalc rsc)
598                 {
599                         return rsc
600                                 .AddFixed(2)
601                                 .WriteStringIndex()
602                                 .WriteGuidIndex()
603                                 .WriteGuidIndex()
604                                 .WriteGuidIndex()
605                                 .Value;
606                 }
607
608                 internal void Add(short generation, int name, int mvid, int encid, int encbaseid)
609                 {
610                         Record record = new Record();
611                         record.Generation = generation;
612                         record.Name = name;
613                         record.Mvid = mvid;
614                         record.EncId = encid;
615                         record.EncBaseId = encbaseid;
616                         AddRecord(record);
617                 }
618         }
619
620         sealed class TypeRefTable : Table<TypeRefTable.Record>
621         {
622                 internal const int Index = 0x01;
623
624                 internal struct Record
625                 {
626                         internal int ResolutionScope;
627                         internal int TypeName;
628                         internal int TypeNameSpace;
629                 }
630
631                 internal override void Read(MetadataReader mr)
632                 {
633                         for (int i = 0; i < records.Length; i++)
634                         {
635                                 records[i].ResolutionScope = mr.ReadResolutionScope();
636                                 records[i].TypeName = mr.ReadStringIndex();
637                                 records[i].TypeNameSpace = mr.ReadStringIndex();
638                         }
639                 }
640
641                 internal override void Write(MetadataWriter mw)
642                 {
643                         for (int i = 0; i < rowCount; i++)
644                         {
645                                 mw.WriteResolutionScope(records[i].ResolutionScope);
646                                 mw.WriteStringIndex(records[i].TypeName);
647                                 mw.WriteStringIndex(records[i].TypeNameSpace);
648                         }
649                 }
650
651                 protected override int GetRowSize(RowSizeCalc rsc)
652                 {
653                         return rsc
654                                 .WriteResolutionScope()
655                                 .WriteStringIndex()
656                                 .WriteStringIndex()
657                                 .Value;
658                 }
659
660                 internal void Fixup(ModuleBuilder moduleBuilder)
661                 {
662                         for (int i = 0; i < rowCount; i++)
663                         {
664                                 moduleBuilder.FixupPseudoToken(ref records[i].ResolutionScope);
665                         }
666                 }
667         }
668
669         sealed class TypeDefTable : Table<TypeDefTable.Record>
670         {
671                 internal const int Index = 0x02;
672
673                 internal struct Record
674                 {
675                         internal int Flags;
676                         internal int TypeName;
677                         internal int TypeNamespace;
678                         internal int Extends;
679                         internal int FieldList;
680                         internal int MethodList;
681                 }
682
683                 internal override void Read(MetadataReader mr)
684                 {
685                         for (int i = 0; i < records.Length; i++)
686                         {
687                                 records[i].Flags = mr.ReadInt32();
688                                 records[i].TypeName = mr.ReadStringIndex();
689                                 records[i].TypeNamespace = mr.ReadStringIndex();
690                                 records[i].Extends = mr.ReadTypeDefOrRef();
691                                 records[i].FieldList = mr.ReadField();
692                                 records[i].MethodList = mr.ReadMethodDef();
693                         }
694                 }
695
696                 internal override void Write(MetadataWriter mw)
697                 {
698                         mw.ModuleBuilder.WriteTypeDefTable(mw);
699                 }
700
701                 internal int AllocToken()
702                 {
703                         return 0x02000000 + AddVirtualRecord();
704                 }
705
706                 protected override int GetRowSize(RowSizeCalc rsc)
707                 {
708                         return rsc
709                                 .AddFixed(4)
710                                 .WriteStringIndex()
711                                 .WriteStringIndex()
712                                 .WriteTypeDefOrRef()
713                                 .WriteField()
714                                 .WriteMethodDef()
715                                 .Value;
716                 }
717         }
718
719         sealed class FieldPtrTable : Table<int>
720         {
721                 internal const int Index = 0x03;
722
723                 internal override void Read(MetadataReader mr)
724                 {
725                         for (int i = 0; i < records.Length; i++)
726                         {
727                                 records[i] = mr.ReadField();
728                         }
729                 }
730         }
731
732         sealed class FieldTable : Table<FieldTable.Record>
733         {
734                 internal const int Index = 0x04;
735
736                 internal struct Record
737                 {
738                         internal short Flags;
739                         internal int Name;
740                         internal int Signature;
741                 }
742
743                 internal override void Read(MetadataReader mr)
744                 {
745                         for (int i = 0; i < records.Length; i++)
746                         {
747                                 records[i].Flags = mr.ReadInt16();
748                                 records[i].Name = mr.ReadStringIndex();
749                                 records[i].Signature = mr.ReadBlobIndex();
750                         }
751                 }
752
753                 internal override void Write(MetadataWriter mw)
754                 {
755                         mw.ModuleBuilder.WriteFieldTable(mw);
756                 }
757
758                 protected override int GetRowSize(RowSizeCalc rsc)
759                 {
760                         return rsc
761                                 .AddFixed(2)
762                                 .WriteStringIndex()
763                                 .WriteBlobIndex()
764                                 .Value;
765                 }
766         }
767
768         sealed class MethodPtrTable : Table<int>
769         {
770                 internal const int Index = 0x05;
771
772                 internal override void Read(MetadataReader mr)
773                 {
774                         for (int i = 0; i < records.Length; i++)
775                         {
776                                 records[i] = mr.ReadMethodDef();
777                         }
778                 }
779         }
780
781         sealed class MethodDefTable : Table<MethodDefTable.Record>
782         {
783                 internal const int Index = 0x06;
784                 private int baseRVA;
785
786                 internal struct Record
787                 {
788                         internal int RVA;
789                         internal short ImplFlags;
790                         internal short Flags;
791                         internal int Name;
792                         internal int Signature;
793                         internal int ParamList;
794                 }
795
796                 internal override void Read(MetadataReader mr)
797                 {
798                         for (int i = 0; i < records.Length; i++)
799                         {
800                                 records[i].RVA = mr.ReadInt32();
801                                 records[i].ImplFlags = mr.ReadInt16();
802                                 records[i].Flags = mr.ReadInt16();
803                                 records[i].Name = mr.ReadStringIndex();
804                                 records[i].Signature = mr.ReadBlobIndex();
805                                 records[i].ParamList = mr.ReadParam();
806                         }
807                 }
808
809                 internal override void Write(MetadataWriter mw)
810                 {
811                         mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw);
812                 }
813
814                 protected override int GetRowSize(RowSizeCalc rsc)
815                 {
816                         return rsc
817                                 .AddFixed(8)
818                                 .WriteStringIndex()
819                                 .WriteBlobIndex()
820                                 .WriteParam()
821                                 .Value;
822                 }
823
824                 internal void Fixup(TextSection code)
825                 {
826                         baseRVA = (int)code.MethodBodiesRVA;
827                 }
828         }
829
830         sealed class ParamPtrTable : Table<int>
831         {
832                 internal const int Index = 0x07;
833
834                 internal override void Read(MetadataReader mr)
835                 {
836                         for (int i = 0; i < records.Length; i++)
837                         {
838                                 records[i] = mr.ReadParam();
839                         }
840                 }
841         }
842
843         sealed class ParamTable : Table<ParamTable.Record>
844         {
845                 internal const int Index = 0x08;
846
847                 internal struct Record
848                 {
849                         internal short Flags;
850                         internal short Sequence;
851                         internal int Name;
852                 }
853
854                 internal override void Read(MetadataReader mr)
855                 {
856                         for (int i = 0; i < records.Length; i++)
857                         {
858                                 records[i].Flags = mr.ReadInt16();
859                                 records[i].Sequence = mr.ReadInt16();
860                                 records[i].Name = mr.ReadStringIndex();
861                         }
862                 }
863
864                 internal override void Write(MetadataWriter mw)
865                 {
866                         mw.ModuleBuilder.WriteParamTable(mw);
867                 }
868
869                 protected override int GetRowSize(RowSizeCalc rsc)
870                 {
871                         return rsc
872                                 .AddFixed(4)
873                                 .WriteStringIndex()
874                                 .Value;
875                 }
876         }
877
878         sealed class InterfaceImplTable : SortedTable<InterfaceImplTable.Record>
879         {
880                 internal const int Index = 0x09;
881
882                 internal struct Record : ISortKey
883                 {
884                         internal int Class;
885                         internal int Interface;
886
887                         int ISortKey.Key
888                         {
889                                 get { return Class; }
890                         }
891                 }
892
893                 internal override void Read(MetadataReader mr)
894                 {
895                         for (int i = 0; i < records.Length; i++)
896                         {
897                                 records[i].Class = mr.ReadTypeDef();
898                                 records[i].Interface = mr.ReadTypeDefOrRef();
899                         }
900                 }
901
902                 internal override void Write(MetadataWriter mw)
903                 {
904                         for (int i = 0; i < rowCount; i++)
905                         {
906                                 mw.WriteTypeDef(records[i].Class);
907                                 mw.WriteEncodedTypeDefOrRef(records[i].Interface);
908                         }
909                 }
910
911                 protected override int GetRowSize(RowSizeCalc rsc)
912                 {
913                         return rsc
914                                 .WriteTypeDef()
915                                 .WriteTypeDefOrRef()
916                                 .Value;
917                 }
918
919                 internal void Fixup()
920                 {
921                         for (int i = 0; i < rowCount; i++)
922                         {
923                                 int token = records[i].Interface;
924                                 switch (token >> 24)
925                                 {
926                                         case 0:
927                                                 break;
928                                         case TypeDefTable.Index:
929                                                 token = (token & 0xFFFFFF) << 2 | 0;
930                                                 break;
931                                         case TypeRefTable.Index:
932                                                 token = (token & 0xFFFFFF) << 2 | 1;
933                                                 break;
934                                         case TypeSpecTable.Index:
935                                                 token = (token & 0xFFFFFF) << 2 | 2;
936                                                 break;
937                                         default:
938                                                 throw new InvalidOperationException();
939                                 }
940                                 records[i].Interface = token;
941                         }
942                         // LAMESPEC the CLI spec says that InterfaceImpl should be sorted by { Class, Interface },
943                         // but it appears to only be necessary to sort by Class (and csc emits InterfaceImpl records in
944                         // source file order, so to be able to support round tripping, we need to retain ordering as well).
945                         Sort();
946                 }
947         }
948
949         sealed class MemberRefTable : Table<MemberRefTable.Record>
950         {
951                 internal const int Index = 0x0A;
952
953                 internal struct Record
954                 {
955                         internal int Class;
956                         internal int Name;
957                         internal int Signature;
958                 }
959
960                 internal override void Read(MetadataReader mr)
961                 {
962                         for (int i = 0; i < records.Length; i++)
963                         {
964                                 records[i].Class = mr.ReadMemberRefParent();
965                                 records[i].Name = mr.ReadStringIndex();
966                                 records[i].Signature = mr.ReadBlobIndex();
967                         }
968                 }
969
970                 internal override void Write(MetadataWriter mw)
971                 {
972                         for (int i = 0; i < rowCount; i++)
973                         {
974                                 mw.WriteMemberRefParent(records[i].Class);
975                                 mw.WriteStringIndex(records[i].Name);
976                                 mw.WriteBlobIndex(records[i].Signature);
977                         }
978                 }
979
980                 protected override int GetRowSize(RowSizeCalc rsc)
981                 {
982                         return rsc
983                                 .WriteMemberRefParent()
984                                 .WriteStringIndex()
985                                 .WriteBlobIndex()
986                                 .Value;
987                 }
988
989                 internal int FindOrAddRecord(Record record)
990                 {
991                         for (int i = 0; i < rowCount; i++)
992                         {
993                                 if (records[i].Class == record.Class
994                                         && records[i].Name == record.Name
995                                         && records[i].Signature == record.Signature)
996                                 {
997                                         return i + 1;
998                                 }
999                         }
1000                         return AddRecord(record);
1001                 }
1002
1003                 internal void Fixup(ModuleBuilder moduleBuilder)
1004                 {
1005                         for (int i = 0; i < rowCount; i++)
1006                         {
1007                                 moduleBuilder.FixupPseudoToken(ref records[i].Class);
1008                         }
1009                 }
1010         }
1011
1012         sealed class ConstantTable : SortedTable<ConstantTable.Record>
1013         {
1014                 internal const int Index = 0x0B;
1015
1016                 internal struct Record : ISortKey
1017                 {
1018                         internal short Type;
1019                         internal int Parent;
1020                         internal int Value;
1021
1022                         int ISortKey.Key
1023                         {
1024                                 get { return Parent; }
1025                         }
1026                 }
1027
1028                 internal override void Read(MetadataReader mr)
1029                 {
1030                         for (int i = 0; i < records.Length; i++)
1031                         {
1032                                 records[i].Type = mr.ReadInt16();
1033                                 records[i].Parent = mr.ReadHasConstant();
1034                                 records[i].Value = mr.ReadBlobIndex();
1035                         }
1036                 }
1037
1038                 internal override void Write(MetadataWriter mw)
1039                 {
1040                         for (int i = 0; i < rowCount; i++)
1041                         {
1042                                 mw.Write(records[i].Type);
1043                                 mw.WriteHasConstant(records[i].Parent);
1044                                 mw.WriteBlobIndex(records[i].Value);
1045                         }
1046                 }
1047
1048                 protected override int GetRowSize(RowSizeCalc rsc)
1049                 {
1050                         return rsc
1051                                 .AddFixed(2)
1052                                 .WriteHasConstant()
1053                                 .WriteBlobIndex()
1054                                 .Value;
1055                 }
1056
1057                 internal void Fixup(ModuleBuilder moduleBuilder)
1058                 {
1059                         for (int i = 0; i < rowCount; i++)
1060                         {
1061                                 int token = records[i].Parent;
1062                                 moduleBuilder.FixupPseudoToken(ref token);
1063                                 // do the HasConstant encoding, so that we can sort the table
1064                                 switch (token >> 24)
1065                                 {
1066                                         case FieldTable.Index:
1067                                                 records[i].Parent = (token & 0xFFFFFF) << 2 | 0;
1068                                                 break;
1069                                         case ParamTable.Index:
1070                                                 records[i].Parent = (token & 0xFFFFFF) << 2 | 1;
1071                                                 break;
1072                                         case PropertyTable.Index:
1073                                                 records[i].Parent = (token & 0xFFFFFF) << 2 | 2;
1074                                                 break;
1075                                         default:
1076                                                 throw new InvalidOperationException();
1077                                 }
1078                         }
1079                         Sort();
1080                 }
1081
1082                 internal object GetRawConstantValue(Module module, int parent)
1083                 {
1084                         foreach (int i in Filter(parent))
1085                         {
1086                                 ByteReader br = module.GetBlob(module.Constant.records[i].Value);
1087                                 switch (module.Constant.records[i].Type)
1088                                 {
1089                                         // see ModuleBuilder.AddConstant for the encodings
1090                                         case Signature.ELEMENT_TYPE_BOOLEAN:
1091                                                 return br.ReadByte() != 0;
1092                                         case Signature.ELEMENT_TYPE_I1:
1093                                                 return br.ReadSByte();
1094                                         case Signature.ELEMENT_TYPE_I2:
1095                                                 return br.ReadInt16();
1096                                         case Signature.ELEMENT_TYPE_I4:
1097                                                 return br.ReadInt32();
1098                                         case Signature.ELEMENT_TYPE_I8:
1099                                                 return br.ReadInt64();
1100                                         case Signature.ELEMENT_TYPE_U1:
1101                                                 return br.ReadByte();
1102                                         case Signature.ELEMENT_TYPE_U2:
1103                                                 return br.ReadUInt16();
1104                                         case Signature.ELEMENT_TYPE_U4:
1105                                                 return br.ReadUInt32();
1106                                         case Signature.ELEMENT_TYPE_U8:
1107                                                 return br.ReadUInt64();
1108                                         case Signature.ELEMENT_TYPE_R4:
1109                                                 return br.ReadSingle();
1110                                         case Signature.ELEMENT_TYPE_R8:
1111                                                 return br.ReadDouble();
1112                                         case Signature.ELEMENT_TYPE_CHAR:
1113                                                 return br.ReadChar();
1114                                         case Signature.ELEMENT_TYPE_STRING:
1115                                                 {
1116                                                         char[] chars = new char[br.Length / 2];
1117                                                         for (int j = 0; j < chars.Length; j++)
1118                                                         {
1119                                                                 chars[j] = br.ReadChar();
1120                                                         }
1121                                                         return new String(chars);
1122                                                 }
1123                                         case Signature.ELEMENT_TYPE_CLASS:
1124                                                 if (br.ReadInt32() != 0)
1125                                                 {
1126                                                         throw new BadImageFormatException();
1127                                                 }
1128                                                 return null;
1129                                         default:
1130                                                 throw new BadImageFormatException();
1131                                 }
1132                         }
1133                         throw new InvalidOperationException();
1134                 }
1135         }
1136
1137         sealed class CustomAttributeTable : SortedTable<CustomAttributeTable.Record>
1138         {
1139                 internal const int Index = 0x0C;
1140
1141                 internal struct Record : ISortKey
1142                 {
1143                         internal int Parent;
1144                         internal int Type;
1145                         internal int Value;
1146
1147                         int ISortKey.Key
1148                         {
1149                                 get { return Parent; }
1150                         }
1151                 }
1152
1153                 internal override void Read(MetadataReader mr)
1154                 {
1155                         for (int i = 0; i < records.Length; i++)
1156                         {
1157                                 records[i].Parent = mr.ReadHasCustomAttribute();
1158                                 records[i].Type = mr.ReadCustomAttributeType();
1159                                 records[i].Value = mr.ReadBlobIndex();
1160                         }
1161                 }
1162
1163                 internal override void Write(MetadataWriter mw)
1164                 {
1165                         for (int i = 0; i < rowCount; i++)
1166                         {
1167                                 mw.WriteHasCustomAttribute(records[i].Parent);
1168                                 mw.WriteCustomAttributeType(records[i].Type);
1169                                 mw.WriteBlobIndex(records[i].Value);
1170                         }
1171                 }
1172
1173                 protected override int GetRowSize(RowSizeCalc rsc)
1174                 {
1175                         return rsc
1176                                 .WriteHasCustomAttribute()
1177                                 .WriteCustomAttributeType()
1178                                 .WriteBlobIndex()
1179                                 .Value;
1180                 }
1181
1182                 internal void Fixup(ModuleBuilder moduleBuilder)
1183                 {
1184                         int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup();
1185                         for (int i = 0; i < rowCount; i++)
1186                         {
1187                                 moduleBuilder.FixupPseudoToken(ref records[i].Type);
1188                                 int token = records[i].Parent;
1189                                 moduleBuilder.FixupPseudoToken(ref token);
1190                                 // do the HasCustomAttribute encoding, so that we can sort the table
1191                                 switch (token >> 24)
1192                                 {
1193                                         case MethodDefTable.Index:
1194                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 0;
1195                                                 break;
1196                                         case FieldTable.Index:
1197                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 1;
1198                                                 break;
1199                                         case TypeRefTable.Index:
1200                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 2;
1201                                                 break;
1202                                         case TypeDefTable.Index:
1203                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 3;
1204                                                 break;
1205                                         case ParamTable.Index:
1206                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 4;
1207                                                 break;
1208                                         case InterfaceImplTable.Index:
1209                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 5;
1210                                                 break;
1211                                         case MemberRefTable.Index:
1212                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 6;
1213                                                 break;
1214                                         case ModuleTable.Index:
1215                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 7;
1216                                                 break;
1217                                         // Permission (8) table doesn't exist in the spec
1218                                         case PropertyTable.Index:
1219                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 9;
1220                                                 break;
1221                                         case EventTable.Index:
1222                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 10;
1223                                                 break;
1224                                         case StandAloneSigTable.Index:
1225                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 11;
1226                                                 break;
1227                                         case ModuleRefTable.Index:
1228                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 12;
1229                                                 break;
1230                                         case TypeSpecTable.Index:
1231                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 13;
1232                                                 break;
1233                                         case AssemblyTable.Index:
1234                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 14;
1235                                                 break;
1236                                         case AssemblyRefTable.Index:
1237                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 15;
1238                                                 break;
1239                                         case FileTable.Index:
1240                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 16;
1241                                                 break;
1242                                         case ExportedTypeTable.Index:
1243                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 17;
1244                                                 break;
1245                                         case ManifestResourceTable.Index:
1246                                                 records[i].Parent = (token & 0xFFFFFF) << 5 | 18;
1247                                                 break;
1248                                         case GenericParamTable.Index:
1249                                                 records[i].Parent = (genericParamFixup[(token & 0xFFFFFF) - 1] + 1) << 5 | 19;
1250                                                 break;
1251                                         default:
1252                                                 throw new InvalidOperationException();
1253                                 }
1254                         }
1255                         Sort();
1256                 }
1257         }
1258
1259         sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>
1260         {
1261                 internal const int Index = 0x0D;
1262
1263                 internal struct Record : ISortKey
1264                 {
1265                         internal int Parent;
1266                         internal int NativeType;
1267
1268                         int ISortKey.Key
1269                         {
1270                                 get { return Parent; }
1271                         }
1272                 }
1273
1274                 internal override void Read(MetadataReader mr)
1275                 {
1276                         for (int i = 0; i < records.Length; i++)
1277                         {
1278                                 records[i].Parent = mr.ReadHasFieldMarshal();
1279                                 records[i].NativeType = mr.ReadBlobIndex();
1280                         }
1281                 }
1282
1283                 internal override void Write(MetadataWriter mw)
1284                 {
1285                         for (int i = 0; i < rowCount; i++)
1286                         {
1287                                 mw.WriteHasFieldMarshal(records[i].Parent);
1288                                 mw.WriteBlobIndex(records[i].NativeType);
1289                         }
1290                 }
1291
1292                 protected override int GetRowSize(RowSizeCalc rsc)
1293                 {
1294                         return rsc
1295                                 .WriteHasFieldMarshal()
1296                                 .WriteBlobIndex()
1297                                 .Value;
1298                 }
1299
1300                 internal void Fixup(ModuleBuilder moduleBuilder)
1301                 {
1302                         for (int i = 0; i < rowCount; i++)
1303                         {
1304                                 int token = moduleBuilder.ResolvePseudoToken(records[i].Parent);
1305                                 // do the HasFieldMarshal encoding, so that we can sort the table
1306                                 switch (token >> 24)
1307                                 {
1308                                         case FieldTable.Index:
1309                                                 records[i].Parent = (token & 0xFFFFFF) << 1 | 0;
1310                                                 break;
1311                                         case ParamTable.Index:
1312                                                 records[i].Parent = (token & 0xFFFFFF) << 1 | 1;
1313                                                 break;
1314                                         default:
1315                                                 throw new InvalidOperationException();
1316                                 }
1317                         }
1318                         Sort();
1319                 }
1320         }
1321
1322         sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>
1323         {
1324                 internal const int Index = 0x0E;
1325
1326                 internal struct Record : ISortKey
1327                 {
1328                         internal short Action;
1329                         internal int Parent;
1330                         internal int PermissionSet;
1331
1332                         int ISortKey.Key
1333                         {
1334                                 get { return Parent; }
1335                         }
1336                 }
1337
1338                 internal override void Read(MetadataReader mr)
1339                 {
1340                         for (int i = 0; i < records.Length; i++)
1341                         {
1342                                 records[i].Action = mr.ReadInt16();
1343                                 records[i].Parent = mr.ReadHasDeclSecurity();
1344                                 records[i].PermissionSet = mr.ReadBlobIndex();
1345                         }
1346                 }
1347
1348                 internal override void Write(MetadataWriter mw)
1349                 {
1350                         for (int i = 0; i < rowCount; i++)
1351                         {
1352                                 mw.Write(records[i].Action);
1353                                 mw.WriteHasDeclSecurity(records[i].Parent);
1354                                 mw.WriteBlobIndex(records[i].PermissionSet);
1355                         }
1356                 }
1357
1358                 protected override int GetRowSize(RowSizeCalc rsc)
1359                 {
1360                         return rsc
1361                                 .AddFixed(2)
1362                                 .WriteHasDeclSecurity()
1363                                 .WriteBlobIndex()
1364                                 .Value;
1365                 }
1366
1367                 internal void Fixup(ModuleBuilder moduleBuilder)
1368                 {
1369                         for (int i = 0; i < rowCount; i++)
1370                         {
1371                                 int token = records[i].Parent;
1372                                 moduleBuilder.FixupPseudoToken(ref token);
1373                                 // do the HasDeclSecurity encoding, so that we can sort the table
1374                                 switch (token >> 24)
1375                                 {
1376                                         case TypeDefTable.Index:
1377                                                 token = (token & 0xFFFFFF) << 2 | 0;
1378                                                 break;
1379                                         case MethodDefTable.Index:
1380                                                 token = (token & 0xFFFFFF) << 2 | 1;
1381                                                 break;
1382                                         case AssemblyTable.Index:
1383                                                 token = (token & 0xFFFFFF) << 2 | 2;
1384                                                 break;
1385                                         default:
1386                                                 throw new InvalidOperationException();
1387                                 }
1388                                 records[i].Parent = token;
1389                         }
1390                         Sort();
1391                 }
1392         }
1393
1394         sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>
1395         {
1396                 internal const int Index = 0x0f;
1397
1398                 internal struct Record : ISortKey
1399                 {
1400                         internal short PackingSize;
1401                         internal int ClassSize;
1402                         internal int Parent;
1403
1404                         int ISortKey.Key
1405                         {
1406                                 get { return Parent; }
1407                         }
1408                 }
1409
1410                 internal override void Read(MetadataReader mr)
1411                 {
1412                         for (int i = 0; i < records.Length; i++)
1413                         {
1414                                 records[i].PackingSize = mr.ReadInt16();
1415                                 records[i].ClassSize = mr.ReadInt32();
1416                                 records[i].Parent = mr.ReadTypeDef();
1417                         }
1418                 }
1419
1420                 internal override void Write(MetadataWriter mw)
1421                 {
1422                         Sort();
1423                         for (int i = 0; i < rowCount; i++)
1424                         {
1425                                 mw.Write(records[i].PackingSize);
1426                                 mw.Write(records[i].ClassSize);
1427                                 mw.WriteTypeDef(records[i].Parent);
1428                         }
1429                 }
1430
1431                 protected override int GetRowSize(RowSizeCalc rsc)
1432                 {
1433                         return rsc
1434                                 .AddFixed(6)
1435                                 .WriteTypeDef()
1436                                 .Value;
1437                 }
1438         }
1439
1440         sealed class FieldLayoutTable : SortedTable<FieldLayoutTable.Record>
1441         {
1442                 internal const int Index = 0x10;
1443
1444                 internal struct Record : ISortKey
1445                 {
1446                         internal int Offset;
1447                         internal int Field;
1448
1449                         int ISortKey.Key
1450                         {
1451                                 get { return Field; }
1452                         }
1453                 }
1454
1455                 internal override void Read(MetadataReader mr)
1456                 {
1457                         for (int i = 0; i < records.Length; i++)
1458                         {
1459                                 records[i].Offset = mr.ReadInt32();
1460                                 records[i].Field = mr.ReadField();
1461                         }
1462                 }
1463
1464                 internal override void Write(MetadataWriter mw)
1465                 {
1466                         for (int i = 0; i < rowCount; i++)
1467                         {
1468                                 mw.Write(records[i].Offset);
1469                                 mw.WriteField(records[i].Field);
1470                         }
1471                 }
1472
1473                 protected override int GetRowSize(RowSizeCalc rsc)
1474                 {
1475                         return rsc
1476                                 .AddFixed(4)
1477                                 .WriteField()
1478                                 .Value;
1479                 }
1480
1481                 internal void Fixup(ModuleBuilder moduleBuilder)
1482                 {
1483                         for (int i = 0; i < rowCount; i++)
1484                         {
1485                                 records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
1486                         }
1487                         Sort();
1488                 }
1489         }
1490
1491         sealed class StandAloneSigTable : Table<int>
1492         {
1493                 internal const int Index = 0x11;
1494
1495                 internal override void Read(MetadataReader mr)
1496                 {
1497                         for (int i = 0; i < records.Length; i++)
1498                         {
1499                                 records[i] = mr.ReadBlobIndex();
1500                         }
1501                 }
1502
1503                 internal override void Write(MetadataWriter mw)
1504                 {
1505                         for (int i = 0; i < rowCount; i++)
1506                         {
1507                                 mw.WriteBlobIndex(records[i]);
1508                         }
1509                 }
1510
1511                 protected override int GetRowSize(Table.RowSizeCalc rsc)
1512                 {
1513                         return rsc.WriteBlobIndex().Value;
1514                 }
1515
1516                 internal int FindOrAddRecord(int blob)
1517                 {
1518                         for (int i = 0; i < rowCount; i++)
1519                         {
1520                                 if (records[i] == blob)
1521                                 {
1522                                         return i + 1;
1523                                 }
1524                         }
1525                         return AddRecord(blob);
1526                 }
1527         }
1528
1529         sealed class EventMapTable : SortedTable<EventMapTable.Record>
1530         {
1531                 internal const int Index = 0x12;
1532
1533                 internal struct Record : ISortKey
1534                 {
1535                         internal int Parent;
1536                         internal int EventList;
1537
1538                         int ISortKey.Key
1539                         {
1540                                 get { return Parent; }
1541                         }
1542                 }
1543
1544                 internal override void Read(MetadataReader mr)
1545                 {
1546                         for (int i = 0; i < records.Length; i++)
1547                         {
1548                                 records[i].Parent = mr.ReadTypeDef();
1549                                 records[i].EventList = mr.ReadEvent();
1550                         }
1551                 }
1552
1553                 internal override void Write(MetadataWriter mw)
1554                 {
1555                         for (int i = 0; i < rowCount; i++)
1556                         {
1557                                 mw.WriteTypeDef(records[i].Parent);
1558                                 mw.WriteEvent(records[i].EventList);
1559                         }
1560                 }
1561
1562                 protected override int GetRowSize(RowSizeCalc rsc)
1563                 {
1564                         return rsc
1565                                 .WriteTypeDef()
1566                                 .WriteEvent()
1567                                 .Value;
1568                 }
1569         }
1570
1571         sealed class EventPtrTable : Table<int>
1572         {
1573                 internal const int Index = 0x13;
1574
1575                 internal override void Read(MetadataReader mr)
1576                 {
1577                         for (int i = 0; i < records.Length; i++)
1578                         {
1579                                 records[i] = mr.ReadEvent();
1580                         }
1581                 }
1582         }
1583
1584         sealed class EventTable : Table<EventTable.Record>
1585         {
1586                 internal const int Index = 0x14;
1587
1588                 internal struct Record
1589                 {
1590                         internal short EventFlags;
1591                         internal int Name;
1592                         internal int EventType;
1593                 }
1594
1595                 internal override void Read(MetadataReader mr)
1596                 {
1597                         for (int i = 0; i < records.Length; i++)
1598                         {
1599                                 records[i].EventFlags = mr.ReadInt16();
1600                                 records[i].Name = mr.ReadStringIndex();
1601                                 records[i].EventType = mr.ReadTypeDefOrRef();
1602                         }
1603                 }
1604
1605                 internal override void Write(MetadataWriter mw)
1606                 {
1607                         for (int i = 0; i < rowCount; i++)
1608                         {
1609                                 mw.Write(records[i].EventFlags);
1610                                 mw.WriteStringIndex(records[i].Name);
1611                                 mw.WriteTypeDefOrRef(records[i].EventType);
1612                         }
1613                 }
1614
1615                 protected override int GetRowSize(RowSizeCalc rsc)
1616                 {
1617                         return rsc
1618                                 .AddFixed(2)
1619                                 .WriteStringIndex()
1620                                 .WriteTypeDefOrRef()
1621                                 .Value;
1622                 }
1623         }
1624
1625         sealed class PropertyMapTable : SortedTable<PropertyMapTable.Record>
1626         {
1627                 internal const int Index = 0x15;
1628
1629                 internal struct Record : ISortKey
1630                 {
1631                         internal int Parent;
1632                         internal int PropertyList;
1633
1634                         int ISortKey.Key
1635                         {
1636                                 get { return Parent; }
1637                         }
1638                 }
1639
1640                 internal override void Read(MetadataReader mr)
1641                 {
1642                         for (int i = 0; i < records.Length; i++)
1643                         {
1644                                 records[i].Parent = mr.ReadTypeDef();
1645                                 records[i].PropertyList = mr.ReadProperty();
1646                         }
1647                 }
1648
1649                 internal override void Write(MetadataWriter mw)
1650                 {
1651                         for (int i = 0; i < rowCount; i++)
1652                         {
1653                                 mw.WriteTypeDef(records[i].Parent);
1654                                 mw.WriteProperty(records[i].PropertyList);
1655                         }
1656                 }
1657
1658                 protected override int GetRowSize(RowSizeCalc rsc)
1659                 {
1660                         return rsc
1661                                 .WriteTypeDef()
1662                                 .WriteProperty()
1663                                 .Value;
1664                 }
1665         }
1666
1667         sealed class PropertyPtrTable : Table<int>
1668         {
1669                 internal const int Index = 0x16;
1670
1671                 internal override void Read(MetadataReader mr)
1672                 {
1673                         for (int i = 0; i < records.Length; i++)
1674                         {
1675                                 records[i] = mr.ReadProperty();
1676                         }
1677                 }
1678         }
1679
1680         sealed class PropertyTable : Table<PropertyTable.Record>
1681         {
1682                 internal const int Index = 0x17;
1683
1684                 internal struct Record
1685                 {
1686                         internal short Flags;
1687                         internal int Name;
1688                         internal int Type;
1689                 }
1690
1691                 internal override void Read(MetadataReader mr)
1692                 {
1693                         for (int i = 0; i < records.Length; i++)
1694                         {
1695                                 records[i].Flags = mr.ReadInt16();
1696                                 records[i].Name = mr.ReadStringIndex();
1697                                 records[i].Type = mr.ReadBlobIndex();
1698                         }
1699                 }
1700
1701                 internal override void Write(MetadataWriter mw)
1702                 {
1703                         for (int i = 0; i < rowCount; i++)
1704                         {
1705                                 mw.Write(records[i].Flags);
1706                                 mw.WriteStringIndex(records[i].Name);
1707                                 mw.WriteBlobIndex(records[i].Type);
1708                         }
1709                 }
1710
1711                 protected override int GetRowSize(RowSizeCalc rsc)
1712                 {
1713                         return rsc
1714                                 .AddFixed(2)
1715                                 .WriteStringIndex()
1716                                 .WriteBlobIndex()
1717                                 .Value;
1718                 }
1719         }
1720
1721         sealed class MethodSemanticsTable : SortedTable<MethodSemanticsTable.Record>
1722         {
1723                 internal const int Index = 0x18;
1724
1725                 // semantics
1726                 internal const short Setter = 0x0001;
1727                 internal const short Getter = 0x0002;
1728                 internal const short Other = 0x0004;
1729                 internal const short AddOn = 0x0008;
1730                 internal const short RemoveOn = 0x0010;
1731                 internal const short Fire = 0x0020;
1732
1733                 internal struct Record : ISortKey
1734                 {
1735                         internal short Semantics;
1736                         internal int Method;
1737                         internal int Association;
1738
1739                         int ISortKey.Key
1740                         {
1741                                 get { return Association; }
1742                         }
1743                 }
1744
1745                 internal override void Read(MetadataReader mr)
1746                 {
1747                         for (int i = 0; i < records.Length; i++)
1748                         {
1749                                 records[i].Semantics = mr.ReadInt16();
1750                                 records[i].Method = mr.ReadMethodDef();
1751                                 records[i].Association = mr.ReadHasSemantics();
1752                         }
1753                 }
1754
1755                 internal override void Write(MetadataWriter mw)
1756                 {
1757                         for (int i = 0; i < rowCount; i++)
1758                         {
1759                                 mw.Write(records[i].Semantics);
1760                                 mw.WriteMethodDef(records[i].Method);
1761                                 mw.WriteHasSemantics(records[i].Association);
1762                         }
1763                 }
1764
1765                 protected override int GetRowSize(RowSizeCalc rsc)
1766                 {
1767                         return rsc
1768                                 .AddFixed(2)
1769                                 .WriteMethodDef()
1770                                 .WriteHasSemantics()
1771                                 .Value;
1772                 }
1773
1774                 internal void Fixup(ModuleBuilder moduleBuilder)
1775                 {
1776                         for (int i = 0; i < rowCount; i++)
1777                         {
1778                                 moduleBuilder.FixupPseudoToken(ref records[i].Method);
1779                                 int token = records[i].Association;
1780                                 // do the HasSemantics encoding, so that we can sort the table
1781                                 switch (token >> 24)
1782                                 {
1783                                         case EventTable.Index:
1784                                                 token = (token & 0xFFFFFF) << 1 | 0;
1785                                                 break;
1786                                         case PropertyTable.Index:
1787                                                 token = (token & 0xFFFFFF) << 1 | 1;
1788                                                 break;
1789                                         default:
1790                                                 throw new InvalidOperationException();
1791                                 }
1792                                 records[i].Association = token;
1793                         }
1794                         Sort();
1795                 }
1796
1797                 internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
1798                 {
1799                         foreach (int i in Filter(token))
1800                         {
1801                                 if ((records[i].Semantics & semantics) != 0)
1802                                 {
1803                                         MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1804                                         if (nonPublic || method.IsPublic)
1805                                         {
1806                                                 return (MethodInfo)method;
1807                                         }
1808                                 }
1809                         }
1810                         return null;
1811                 }
1812
1813                 internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics)
1814                 {
1815                         List<MethodInfo> methods = new List<MethodInfo>();
1816                         foreach (int i in Filter(token))
1817                         {
1818                                 if ((records[i].Semantics & semantics) != 0)
1819                                 {
1820                                         MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1821                                         if (nonPublic || method.IsPublic)
1822                                         {
1823                                                 methods.Add(method);
1824                                         }
1825                                 }
1826                         }
1827                         return methods.ToArray();
1828                 }
1829
1830                 internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isNonPrivate, out bool isStatic)
1831                 {
1832                         isPublic = false;
1833                         isNonPrivate = false;
1834                         isStatic = false;
1835                         foreach (int i in Filter(token))
1836                         {
1837                                 MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1838                                 isPublic |= method.IsPublic;
1839                                 isNonPrivate |= (method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private;
1840                                 isStatic |= method.IsStatic;
1841                         }
1842                 }
1843         }
1844
1845         sealed class MethodImplTable : SortedTable<MethodImplTable.Record>
1846         {
1847                 internal const int Index = 0x19;
1848
1849                 internal struct Record : ISortKey
1850                 {
1851                         internal int Class;
1852                         internal int MethodBody;
1853                         internal int MethodDeclaration;
1854
1855                         int ISortKey.Key
1856                         {
1857                                 get { return Class; }
1858                         }
1859                 }
1860
1861                 internal override void Read(MetadataReader mr)
1862                 {
1863                         for (int i = 0; i < records.Length; i++)
1864                         {
1865                                 records[i].Class = mr.ReadTypeDef();
1866                                 records[i].MethodBody = mr.ReadMethodDefOrRef();
1867                                 records[i].MethodDeclaration = mr.ReadMethodDefOrRef();
1868                         }
1869                 }
1870
1871                 internal override void Write(MetadataWriter mw)
1872                 {
1873                         for (int i = 0; i < rowCount; i++)
1874                         {
1875                                 mw.WriteTypeDef(records[i].Class);
1876                                 mw.WriteMethodDefOrRef(records[i].MethodBody);
1877                                 mw.WriteMethodDefOrRef(records[i].MethodDeclaration);
1878                         }
1879                 }
1880
1881                 protected override int GetRowSize(RowSizeCalc rsc)
1882                 {
1883                         return rsc
1884                                 .WriteTypeDef()
1885                                 .WriteMethodDefOrRef()
1886                                 .WriteMethodDefOrRef()
1887                                 .Value;
1888                 }
1889
1890                 internal void Fixup(ModuleBuilder moduleBuilder)
1891                 {
1892                         for (int i = 0; i < rowCount; i++)
1893                         {
1894                                 moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
1895                                 moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
1896                         }
1897                         Sort();
1898                 }
1899         }
1900
1901         sealed class ModuleRefTable : Table<int>
1902         {
1903                 internal const int Index = 0x1A;
1904
1905                 internal override void Read(MetadataReader mr)
1906                 {
1907                         for (int i = 0; i < records.Length; i++)
1908                         {
1909                                 records[i] = mr.ReadStringIndex();
1910                         }
1911                 }
1912
1913                 internal override void Write(MetadataWriter mw)
1914                 {
1915                         for (int i = 0; i < rowCount; i++)
1916                         {
1917                                 mw.WriteStringIndex(records[i]);
1918                         }
1919                 }
1920
1921                 protected override int GetRowSize(RowSizeCalc rsc)
1922                 {
1923                         return rsc
1924                                 .WriteStringIndex()
1925                                 .Value;
1926                 }
1927
1928                 internal int FindOrAddRecord(int str)
1929                 {
1930                         for (int i = 0; i < rowCount; i++)
1931                         {
1932                                 if (records[i] == str)
1933                                 {
1934                                         return i + 1;
1935                                 }
1936                         }
1937                         return AddRecord(str);
1938                 }
1939         }
1940
1941         sealed class TypeSpecTable : Table<int>
1942         {
1943                 internal const int Index = 0x1B;
1944
1945                 internal override void Read(MetadataReader mr)
1946                 {
1947                         for (int i = 0; i < records.Length; i++)
1948                         {
1949                                 records[i] = mr.ReadBlobIndex();
1950                         }
1951                 }
1952
1953                 internal override void Write(MetadataWriter mw)
1954                 {
1955                         for (int i = 0; i < rowCount; i++)
1956                         {
1957                                 mw.WriteBlobIndex(records[i]);
1958                         }
1959                 }
1960
1961                 protected override int GetRowSize(Table.RowSizeCalc rsc)
1962                 {
1963                         return rsc.WriteBlobIndex().Value;
1964                 }
1965         }
1966
1967         sealed class ImplMapTable : SortedTable<ImplMapTable.Record>
1968         {
1969                 internal const int Index = 0x1C;
1970
1971                 internal struct Record : ISortKey
1972                 {
1973                         internal short MappingFlags;
1974                         internal int MemberForwarded;
1975                         internal int ImportName;
1976                         internal int ImportScope;
1977
1978                         int ISortKey.Key
1979                         {
1980                                 get { return MemberForwarded; }
1981                         }
1982                 }
1983
1984                 internal override void Read(MetadataReader mr)
1985                 {
1986                         for (int i = 0; i < records.Length; i++)
1987                         {
1988                                 records[i].MappingFlags = mr.ReadInt16();
1989                                 records[i].MemberForwarded = mr.ReadMemberForwarded();
1990                                 records[i].ImportName = mr.ReadStringIndex();
1991                                 records[i].ImportScope = mr.ReadModuleRef();
1992                         }
1993                 }
1994
1995                 internal override void Write(MetadataWriter mw)
1996                 {
1997                         for (int i = 0; i < rowCount; i++)
1998                         {
1999                                 mw.Write(records[i].MappingFlags);
2000                                 mw.WriteMemberForwarded(records[i].MemberForwarded);
2001                                 mw.WriteStringIndex(records[i].ImportName);
2002                                 mw.WriteModuleRef(records[i].ImportScope);
2003                         }
2004                 }
2005
2006                 protected override int GetRowSize(RowSizeCalc rsc)
2007                 {
2008                         return rsc
2009                                 .AddFixed(2)
2010                                 .WriteMemberForwarded()
2011                                 .WriteStringIndex()
2012                                 .WriteModuleRef()
2013                                 .Value;
2014                 }
2015
2016                 internal void Fixup(ModuleBuilder moduleBuilder)
2017                 {
2018                         for (int i = 0; i < rowCount; i++)
2019                         {
2020                                 moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
2021                         }
2022                         Sort();
2023                 }
2024         }
2025
2026         sealed class FieldRVATable : SortedTable<FieldRVATable.Record>
2027         {
2028                 internal const int Index = 0x1D;
2029
2030                 internal struct Record : ISortKey
2031                 {
2032                         internal int RVA;               // we set the high bit to signify that the RVA is in the CIL stream (instead of .sdata)
2033                         internal int Field;
2034
2035                         int ISortKey.Key
2036                         {
2037                                 get { return Field; }
2038                         }
2039                 }
2040
2041                 internal override void Read(MetadataReader mr)
2042                 {
2043                         for (int i = 0; i < records.Length; i++)
2044                         {
2045                                 records[i].RVA = mr.ReadInt32();
2046                                 records[i].Field = mr.ReadField();
2047                         }
2048                 }
2049
2050                 internal override void Write(MetadataWriter mw)
2051                 {
2052                         for (int i = 0; i < rowCount; i++)
2053                         {
2054                                 mw.Write(records[i].RVA);
2055                                 mw.WriteField(records[i].Field);
2056                         }
2057                 }
2058
2059                 protected override int GetRowSize(RowSizeCalc rsc)
2060                 {
2061                         return rsc
2062                                 .AddFixed(4)
2063                                 .WriteField()
2064                                 .Value;
2065                 }
2066
2067                 internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA, int cilRVA)
2068                 {
2069                         for (int i = 0; i < rowCount; i++)
2070                         {
2071                                 if (records[i].RVA < 0)
2072                                 {
2073                                         records[i].RVA = (records[i].RVA & 0x7fffffff) + cilRVA;
2074                                 }
2075                                 else
2076                                 {
2077                                         records[i].RVA += sdataRVA;
2078                                 }
2079                                 moduleBuilder.FixupPseudoToken(ref records[i].Field);
2080                         }
2081                         Sort();
2082                 }
2083         }
2084
2085         sealed class AssemblyTable : Table<AssemblyTable.Record>
2086         {
2087                 internal const int Index = 0x20;
2088
2089                 internal struct Record
2090                 {
2091                         internal int HashAlgId;
2092                         internal ushort MajorVersion;
2093                         internal ushort MinorVersion;
2094                         internal ushort BuildNumber;
2095                         internal ushort RevisionNumber;
2096                         internal int Flags;
2097                         internal int PublicKey;
2098                         internal int Name;
2099                         internal int Culture;
2100                 }
2101
2102                 internal override void Read(MetadataReader mr)
2103                 {
2104                         for (int i = 0; i < records.Length; i++)
2105                         {
2106                                 records[i].HashAlgId = mr.ReadInt32();
2107                                 records[i].MajorVersion = mr.ReadUInt16();
2108                                 records[i].MinorVersion = mr.ReadUInt16();
2109                                 records[i].BuildNumber = mr.ReadUInt16();
2110                                 records[i].RevisionNumber = mr.ReadUInt16();
2111                                 records[i].Flags = mr.ReadInt32();
2112                                 records[i].PublicKey = mr.ReadBlobIndex();
2113                                 records[i].Name = mr.ReadStringIndex();
2114                                 records[i].Culture = mr.ReadStringIndex();
2115                         }
2116                 }
2117
2118                 internal override void Write(MetadataWriter mw)
2119                 {
2120                         for (int i = 0; i < rowCount; i++)
2121                         {
2122                                 mw.Write(records[i].HashAlgId);
2123                                 mw.Write(records[i].MajorVersion);
2124                                 mw.Write(records[i].MinorVersion);
2125                                 mw.Write(records[i].BuildNumber);
2126                                 mw.Write(records[i].RevisionNumber);
2127                                 mw.Write(records[i].Flags);
2128                                 mw.WriteBlobIndex(records[i].PublicKey);
2129                                 mw.WriteStringIndex(records[i].Name);
2130                                 mw.WriteStringIndex(records[i].Culture);
2131                         }
2132                 }
2133
2134                 protected override int GetRowSize(RowSizeCalc rsc)
2135                 {
2136                         return rsc
2137                                 .AddFixed(16)
2138                                 .WriteBlobIndex()
2139                                 .WriteStringIndex()
2140                                 .WriteStringIndex()
2141                                 .Value;
2142                 }
2143         }
2144
2145         sealed class AssemblyRefTable : Table<AssemblyRefTable.Record>
2146         {
2147                 internal const int Index = 0x23;
2148
2149                 internal struct Record
2150                 {
2151                         internal ushort MajorVersion;
2152                         internal ushort MinorVersion;
2153                         internal ushort BuildNumber;
2154                         internal ushort RevisionNumber;
2155                         internal int Flags;
2156                         internal int PublicKeyOrToken;
2157                         internal int Name;
2158                         internal int Culture;
2159                         internal int HashValue;
2160                 }
2161
2162                 internal int FindOrAddRecord(Record rec)
2163                 {
2164                         for (int i = 0; i < rowCount; i++)
2165                         {
2166                                 // note that we ignore HashValue here!
2167                                 if (records[i].Name == rec.Name
2168                                         && records[i].MajorVersion == rec.MajorVersion
2169                                         && records[i].MinorVersion == rec.MinorVersion
2170                                         && records[i].BuildNumber == rec.BuildNumber
2171                                         && records[i].RevisionNumber == rec.RevisionNumber
2172                                         && records[i].Flags == rec.Flags
2173                                         && records[i].PublicKeyOrToken == rec.PublicKeyOrToken
2174                                         && records[i].Culture == rec.Culture
2175                                         )
2176                                 {
2177                                         return i + 1;
2178                                 }
2179                         }
2180                         return AddRecord(rec);
2181                 }
2182
2183                 internal override void Read(MetadataReader mr)
2184                 {
2185                         for (int i = 0; i < records.Length; i++)
2186                         {
2187                                 records[i].MajorVersion = mr.ReadUInt16();
2188                                 records[i].MinorVersion = mr.ReadUInt16();
2189                                 records[i].BuildNumber = mr.ReadUInt16();
2190                                 records[i].RevisionNumber = mr.ReadUInt16();
2191                                 records[i].Flags = mr.ReadInt32();
2192                                 records[i].PublicKeyOrToken = mr.ReadBlobIndex();
2193                                 records[i].Name = mr.ReadStringIndex();
2194                                 records[i].Culture = mr.ReadStringIndex();
2195                                 records[i].HashValue = mr.ReadBlobIndex();
2196                         }
2197                 }
2198
2199                 internal override void Write(MetadataWriter mw)
2200                 {
2201                         for (int i = 0; i < rowCount; i++)
2202                         {
2203                                 mw.Write(records[i].MajorVersion);
2204                                 mw.Write(records[i].MinorVersion);
2205                                 mw.Write(records[i].BuildNumber);
2206                                 mw.Write(records[i].RevisionNumber);
2207                                 mw.Write(records[i].Flags);
2208                                 mw.WriteBlobIndex(records[i].PublicKeyOrToken);
2209                                 mw.WriteStringIndex(records[i].Name);
2210                                 mw.WriteStringIndex(records[i].Culture);
2211                                 mw.WriteBlobIndex(records[i].HashValue);
2212                         }
2213                 }
2214
2215                 protected override int GetRowSize(RowSizeCalc rsc)
2216                 {
2217                         return rsc
2218                                 .AddFixed(12)
2219                                 .WriteBlobIndex()
2220                                 .WriteStringIndex()
2221                                 .WriteStringIndex()
2222                                 .WriteBlobIndex()
2223                                 .Value;
2224                 }
2225         }
2226
2227         sealed class FileTable : Table<FileTable.Record>
2228         {
2229                 internal const int Index = 0x26;
2230
2231                 internal struct Record
2232                 {
2233                         internal int Flags;
2234                         internal int Name;
2235                         internal int HashValue;
2236                 }
2237
2238                 internal override void Read(MetadataReader mr)
2239                 {
2240                         for (int i = 0; i < records.Length; i++)
2241                         {
2242                                 records[i].Flags = mr.ReadInt32();
2243                                 records[i].Name = mr.ReadStringIndex();
2244                                 records[i].HashValue = mr.ReadBlobIndex();
2245                         }
2246                 }
2247
2248                 internal override void Write(MetadataWriter mw)
2249                 {
2250                         for (int i = 0; i < rowCount; i++)
2251                         {
2252                                 mw.Write(records[i].Flags);
2253                                 mw.WriteStringIndex(records[i].Name);
2254                                 mw.WriteBlobIndex(records[i].HashValue);
2255                         }
2256                 }
2257
2258                 protected override int GetRowSize(RowSizeCalc rsc)
2259                 {
2260                         return rsc
2261                                 .AddFixed(4)
2262                                 .WriteStringIndex()
2263                                 .WriteBlobIndex()
2264                                 .Value;
2265                 }
2266         }
2267
2268         sealed class ExportedTypeTable : Table<ExportedTypeTable.Record>
2269         {
2270                 internal const int Index = 0x27;
2271
2272                 internal struct Record
2273                 {
2274                         internal int Flags;
2275                         internal int TypeDefId;
2276                         internal int TypeName;
2277                         internal int TypeNamespace;
2278                         internal int Implementation;
2279                 }
2280
2281                 internal override void Read(MetadataReader mr)
2282                 {
2283                         for (int i = 0; i < records.Length; i++)
2284                         {
2285                                 records[i].Flags = mr.ReadInt32();
2286                                 records[i].TypeDefId = mr.ReadInt32();
2287                                 records[i].TypeName = mr.ReadStringIndex();
2288                                 records[i].TypeNamespace = mr.ReadStringIndex();
2289                                 records[i].Implementation = mr.ReadImplementation();
2290                         }
2291                 }
2292
2293                 internal override void Write(MetadataWriter mw)
2294                 {
2295                         for (int i = 0; i < rowCount; i++)
2296                         {
2297                                 mw.Write(records[i].Flags);
2298                                 mw.Write(records[i].TypeDefId);
2299                                 mw.WriteStringIndex(records[i].TypeName);
2300                                 mw.WriteStringIndex(records[i].TypeNamespace);
2301                                 mw.WriteImplementation(records[i].Implementation);
2302                         }
2303                 }
2304
2305                 protected override int GetRowSize(RowSizeCalc rsc)
2306                 {
2307                         return rsc
2308                                 .AddFixed(8)
2309                                 .WriteStringIndex()
2310                                 .WriteStringIndex()
2311                                 .WriteImplementation()
2312                                 .Value;
2313                 }
2314
2315                 internal int FindOrAddRecord(Record rec)
2316                 {
2317                         for (int i = 0; i < rowCount; i++)
2318                         {
2319                                 if (records[i].Implementation == rec.Implementation
2320                                         && records[i].TypeName == rec.TypeName
2321                                         && records[i].TypeNamespace == rec.TypeNamespace)
2322                                 {
2323                                         return i + 1;
2324                                 }
2325                         }
2326                         return AddRecord(rec);
2327                 }
2328
2329                 internal void Fixup(ModuleBuilder moduleBuilder)
2330                 {
2331                         for (int i = 0; i < rowCount; i++)
2332                         {
2333                                 moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
2334                         }
2335                 }
2336         }
2337
2338         sealed class ManifestResourceTable : Table<ManifestResourceTable.Record>
2339         {
2340                 internal const int Index = 0x28;
2341
2342                 internal struct Record
2343                 {
2344                         internal int Offset;
2345                         internal int Flags;
2346                         internal int Name;
2347                         internal int Implementation;
2348                 }
2349
2350                 internal override void Read(MetadataReader mr)
2351                 {
2352                         for (int i = 0; i < records.Length; i++)
2353                         {
2354                                 records[i].Offset = mr.ReadInt32();
2355                                 records[i].Flags = mr.ReadInt32();
2356                                 records[i].Name = mr.ReadStringIndex();
2357                                 records[i].Implementation = mr.ReadImplementation();
2358                         }
2359                 }
2360
2361                 internal override void Write(MetadataWriter mw)
2362                 {
2363                         for (int i = 0; i < rowCount; i++)
2364                         {
2365                                 mw.Write(records[i].Offset);
2366                                 mw.Write(records[i].Flags);
2367                                 mw.WriteStringIndex(records[i].Name);
2368                                 mw.WriteImplementation(records[i].Implementation);
2369                         }
2370                 }
2371
2372                 protected override int GetRowSize(RowSizeCalc rsc)
2373                 {
2374                         return rsc
2375                                 .AddFixed(8)
2376                                 .WriteStringIndex()
2377                                 .WriteImplementation()
2378                                 .Value;
2379                 }
2380
2381                 internal void Fixup(ModuleBuilder moduleBuilder)
2382                 {
2383                         for (int i = 0; i < rowCount; i++)
2384                         {
2385                                 moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
2386                         }
2387                 }
2388         }
2389
2390         sealed class NestedClassTable : SortedTable<NestedClassTable.Record>
2391         {
2392                 internal const int Index = 0x29;
2393
2394                 internal struct Record : ISortKey
2395                 {
2396                         internal int NestedClass;
2397                         internal int EnclosingClass;
2398
2399                         int ISortKey.Key
2400                         {
2401                                 get { return NestedClass; }
2402                         }
2403                 }
2404
2405                 internal override void Read(MetadataReader mr)
2406                 {
2407                         for (int i = 0; i < records.Length; i++)
2408                         {
2409                                 records[i].NestedClass = mr.ReadTypeDef();
2410                                 records[i].EnclosingClass = mr.ReadTypeDef();
2411                         }
2412                 }
2413
2414                 internal override void Write(MetadataWriter mw)
2415                 {
2416                         for (int i = 0; i < rowCount; i++)
2417                         {
2418                                 mw.WriteTypeDef(records[i].NestedClass);
2419                                 mw.WriteTypeDef(records[i].EnclosingClass);
2420                         }
2421                 }
2422
2423                 protected override int GetRowSize(RowSizeCalc rsc)
2424                 {
2425                         return rsc
2426                                 .WriteTypeDef()
2427                                 .WriteTypeDef()
2428                                 .Value;
2429                 }
2430
2431                 internal List<int> GetNestedClasses(int enclosingClass)
2432                 {
2433                         List<int> nestedClasses = new List<int>();
2434                         for (int i = 0; i < rowCount; i++)
2435                         {
2436                                 if (records[i].EnclosingClass == enclosingClass)
2437                                 {
2438                                         nestedClasses.Add(records[i].NestedClass);
2439                                 }
2440                         }
2441                         return nestedClasses;
2442                 }
2443         }
2444
2445         sealed class GenericParamTable : SortedTable<GenericParamTable.Record>, IComparer<GenericParamTable.Record>
2446         {
2447                 internal const int Index = 0x2A;
2448
2449                 internal struct Record : ISortKey
2450                 {
2451                         internal short Number;
2452                         internal short Flags;
2453                         internal int Owner;
2454                         internal int Name;
2455                         // not part of the table, we use it to be able to fixup the GenericParamConstraint table
2456                         internal int unsortedIndex;
2457
2458                         int ISortKey.Key
2459                         {
2460                                 get { return Owner; }
2461                         }
2462                 }
2463
2464                 internal override void Read(MetadataReader mr)
2465                 {
2466                         for (int i = 0; i < records.Length; i++)
2467                         {
2468                                 records[i].Number = mr.ReadInt16();
2469                                 records[i].Flags = mr.ReadInt16();
2470                                 records[i].Owner = mr.ReadTypeOrMethodDef();
2471                                 records[i].Name = mr.ReadStringIndex();
2472                         }
2473                 }
2474
2475                 internal override void Write(MetadataWriter mw)
2476                 {
2477                         for (int i = 0; i < rowCount; i++)
2478                         {
2479                                 mw.Write(records[i].Number);
2480                                 mw.Write(records[i].Flags);
2481                                 mw.WriteTypeOrMethodDef(records[i].Owner);
2482                                 mw.WriteStringIndex(records[i].Name);
2483                         }
2484                 }
2485
2486                 protected override int GetRowSize(RowSizeCalc rsc)
2487                 {
2488                         return rsc
2489                                 .AddFixed(4)
2490                                 .WriteTypeOrMethodDef()
2491                                 .WriteStringIndex()
2492                                 .Value;
2493                 }
2494
2495                 internal void Fixup(ModuleBuilder moduleBuilder)
2496                 {
2497                         for (int i = 0; i < rowCount; i++)
2498                         {
2499                                 int token = records[i].Owner;
2500                                 moduleBuilder.FixupPseudoToken(ref token);
2501                                 // do the TypeOrMethodDef encoding, so that we can sort the table
2502                                 switch (token >> 24)
2503                                 {
2504                                         case TypeDefTable.Index:
2505                                                 records[i].Owner = (token & 0xFFFFFF) << 1 | 0;
2506                                                 break;
2507                                         case MethodDefTable.Index:
2508                                                 records[i].Owner = (token & 0xFFFFFF) << 1 | 1;
2509                                                 break;
2510                                         default:
2511                                                 throw new InvalidOperationException();
2512                                 }
2513                                 records[i].unsortedIndex = i;
2514                         }
2515                         // FXBUG the unnecessary (IComparer<Record>) cast is a workaround for a .NET 2.0 C# compiler bug
2516                         Array.Sort(records, 0, rowCount, (IComparer<Record>)this);
2517                 }
2518
2519                 int IComparer<Record>.Compare(Record x, Record y)
2520                 {
2521                         if (x.Owner == y.Owner)
2522                         {
2523                                 return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1);
2524                         }
2525                         return x.Owner > y.Owner ? 1 : -1;
2526                 }
2527
2528                 internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes)
2529                 {
2530                         records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes;
2531                 }
2532
2533                 internal int[] GetIndexFixup()
2534                 {
2535                         int[] array = new int[rowCount];
2536                         for (int i = 0; i < rowCount; i++)
2537                         {
2538                                 array[records[i].unsortedIndex] = i;
2539                         }
2540                         return array;
2541                 }
2542
2543                 internal int FindFirstByOwner(int token)
2544                 {
2545                         foreach (int i in Filter(token))
2546                         {
2547                                 return i;
2548                         }
2549                         return -1;
2550                 }
2551         }
2552
2553         sealed class MethodSpecTable : Table<MethodSpecTable.Record>
2554         {
2555                 internal const int Index = 0x2B;
2556
2557                 internal struct Record
2558                 {
2559                         internal int Method;
2560                         internal int Instantiation;
2561                 }
2562
2563                 internal override void Read(MetadataReader mr)
2564                 {
2565                         for (int i = 0; i < records.Length; i++)
2566                         {
2567                                 records[i].Method = mr.ReadMethodDefOrRef();
2568                                 records[i].Instantiation = mr.ReadBlobIndex();
2569                         }
2570                 }
2571
2572                 internal override void Write(MetadataWriter mw)
2573                 {
2574                         for (int i = 0; i < rowCount; i++)
2575                         {
2576                                 mw.WriteMethodDefOrRef(records[i].Method);
2577                                 mw.WriteBlobIndex(records[i].Instantiation);
2578                         }
2579                 }
2580
2581                 protected override int GetRowSize(RowSizeCalc rsc)
2582                 {
2583                         return rsc
2584                                 .WriteMethodDefOrRef()
2585                                 .WriteBlobIndex()
2586                                 .Value;
2587                 }
2588
2589                 internal int FindOrAddRecord(Record record)
2590                 {
2591                         for (int i = 0; i < rowCount; i++)
2592                         {
2593                                 if (records[i].Method == record.Method
2594                                         && records[i].Instantiation == record.Instantiation)
2595                                 {
2596                                         return i + 1;
2597                                 }
2598                         }
2599                         return AddRecord(record);
2600                 }
2601
2602                 internal void Fixup(ModuleBuilder moduleBuilder)
2603                 {
2604                         for (int i = 0; i < rowCount; i++)
2605                         {
2606                                 moduleBuilder.FixupPseudoToken(ref records[i].Method);
2607                         }
2608                 }
2609         }
2610
2611         sealed class GenericParamConstraintTable : SortedTable<GenericParamConstraintTable.Record>
2612         {
2613                 internal const int Index = 0x2C;
2614
2615                 internal struct Record : ISortKey
2616                 {
2617                         internal int Owner;
2618                         internal int Constraint;
2619
2620                         int ISortKey.Key
2621                         {
2622                                 get { return Owner; }
2623                         }
2624                 }
2625
2626                 internal override void Read(MetadataReader mr)
2627                 {
2628                         for (int i = 0; i < records.Length; i++)
2629                         {
2630                                 records[i].Owner = mr.ReadGenericParam();
2631                                 records[i].Constraint = mr.ReadTypeDefOrRef();
2632                         }
2633                 }
2634
2635                 internal override void Write(MetadataWriter mw)
2636                 {
2637                         for (int i = 0; i < rowCount; i++)
2638                         {
2639                                 mw.WriteGenericParam(records[i].Owner);
2640                                 mw.WriteTypeDefOrRef(records[i].Constraint);
2641                         }
2642                 }
2643
2644                 protected override int GetRowSize(RowSizeCalc rsc)
2645                 {
2646                         return rsc
2647                                 .WriteGenericParam()
2648                                 .WriteTypeDefOrRef()
2649                                 .Value;
2650                 }
2651
2652                 internal void Fixup(ModuleBuilder moduleBuilder)
2653                 {
2654                         int[] fixups = moduleBuilder.GenericParam.GetIndexFixup();
2655                         for (int i = 0; i < rowCount; i++)
2656                         {
2657                                 records[i].Owner = fixups[records[i].Owner - 1] + 1;
2658                         }
2659                         Sort();
2660                 }
2661         }
2662 }