Update mcs/class/System.Core/System/TimeZoneInfo.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>
429                 where T : SortedTable<T>.IRecord
430         {
431                 internal interface IRecord
432                 {
433                         int SortKey { get; }
434                         int FilterKey { get; }
435                 }
436
437                 internal struct Enumerable
438                 {
439                         private readonly SortedTable<T> table;
440                         private readonly int token;
441
442                         internal Enumerable(SortedTable<T> table, int token)
443                         {
444                                 this.table = table;
445                                 this.token = token;
446                         }
447
448                         public Enumerator GetEnumerator()
449                         {
450                                 T[] records = table.records;
451                                 if (!table.Sorted)
452                                 {
453                                         return new Enumerator(records, table.RowCount - 1, -1, token);
454                                 }
455                                 int index = BinarySearch(records, table.RowCount, token & 0xFFFFFF);
456                                 if (index < 0)
457                                 {
458                                         return new Enumerator(null, 0, 1, -1);
459                                 }
460                                 int start = index;
461                                 while (start > 0 && (records[start - 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF))
462                                 {
463                                         start--;
464                                 }
465                                 int end = index;
466                                 int max = table.RowCount - 1;
467                                 while (end < max && (records[end + 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF))
468                                 {
469                                         end++;
470                                 }
471                                 return new Enumerator(records, end, start - 1, token);
472                         }
473
474                         private static int BinarySearch(T[] records, int length, int maskedToken)
475                         {
476                                 int min = 0;
477                                 int max = length - 1;
478                                 while (min <= max)
479                                 {
480                                         int mid = min + ((max - min) / 2);
481                                         int maskedValue = records[mid].FilterKey & 0xFFFFFF;
482                                         if (maskedToken == maskedValue)
483                                         {
484                                                 return mid;
485                                         }
486                                         else if (maskedToken < maskedValue)
487                                         {
488                                                 max = mid - 1;
489                                         }
490                                         else
491                                         {
492                                                 min = mid + 1;
493                                         }
494                                 }
495                                 return -1;
496                         }
497                 }
498
499                 internal struct Enumerator
500                 {
501                         private readonly T[] records;
502                         private readonly int token;
503                         private readonly int max;
504                         private int index;
505
506                         internal Enumerator(T[] records, int max, int index, int token)
507                         {
508                                 this.records = records;
509                                 this.token = token;
510                                 this.max = max;
511                                 this.index = index;
512                         }
513
514                         public int Current
515                         {
516                                 get { return index; }
517                         }
518
519                         public bool MoveNext()
520                         {
521                                 while (index < max)
522                                 {
523                                         index++;
524                                         if (records[index].FilterKey == token)
525                                         {
526                                                 return true;
527                                         }
528                                 }
529                                 return false;
530                         }
531                 }
532
533                 internal Enumerable Filter(int token)
534                 {
535                         return new Enumerable(this, token);
536                 }
537
538                 protected void Sort()
539                 {
540                         ulong[] map = new ulong[rowCount];
541                         for (uint i = 0; i < map.Length; i++)
542                         {
543                                 map[i] = ((ulong)records[i].SortKey << 32) | i;
544                         }
545                         Array.Sort(map);
546                         T[] newRecords = new T[rowCount];
547                         for (int i = 0; i < map.Length; i++)
548                         {
549                                 newRecords[i] = records[(int)map[i]];
550                         }
551                         records = newRecords;
552                 }
553         }
554
555         sealed class ModuleTable : Table<ModuleTable.Record>
556         {
557                 internal const int Index = 0x00;
558
559                 internal struct Record
560                 {
561                         internal short Generation;
562                         internal int Name; // -> StringHeap
563                         internal int Mvid; // -> GuidHeap
564                         internal int EncId; // -> GuidHeap
565                         internal int EncBaseId; // -> GuidHeap
566                 }
567
568                 internal override void Read(MetadataReader mr)
569                 {
570                         for (int i = 0; i < records.Length; i++)
571                         {
572                                 records[i].Generation = mr.ReadInt16();
573                                 records[i].Name = mr.ReadStringIndex();
574                                 records[i].Mvid = mr.ReadGuidIndex();
575                                 records[i].EncId = mr.ReadGuidIndex();
576                                 records[i].EncBaseId = mr.ReadGuidIndex();
577                         }
578                 }
579
580                 internal override void Write(MetadataWriter mw)
581                 {
582                         for (int i = 0; i < rowCount; i++)
583                         {
584                                 mw.Write(records[i].Generation);
585                                 mw.WriteStringIndex(records[i].Name);
586                                 mw.WriteGuidIndex(records[i].Mvid);
587                                 mw.WriteGuidIndex(records[i].EncId);
588                                 mw.WriteGuidIndex(records[i].EncBaseId);
589                         }
590                 }
591
592                 protected override int GetRowSize(RowSizeCalc rsc)
593                 {
594                         return rsc
595                                 .AddFixed(2)
596                                 .WriteStringIndex()
597                                 .WriteGuidIndex()
598                                 .WriteGuidIndex()
599                                 .WriteGuidIndex()
600                                 .Value;
601                 }
602
603                 internal void Add(short generation, int name, int mvid, int encid, int encbaseid)
604                 {
605                         Record record = new Record();
606                         record.Generation = generation;
607                         record.Name = name;
608                         record.Mvid = mvid;
609                         record.EncId = encid;
610                         record.EncBaseId = encbaseid;
611                         AddRecord(record);
612                 }
613         }
614
615         sealed class TypeRefTable : Table<TypeRefTable.Record>
616         {
617                 internal const int Index = 0x01;
618
619                 internal struct Record
620                 {
621                         internal int ResolutionScope;
622                         internal int TypeName;
623                         internal int TypeNameSpace;
624                 }
625
626                 internal override void Read(MetadataReader mr)
627                 {
628                         for (int i = 0; i < records.Length; i++)
629                         {
630                                 records[i].ResolutionScope = mr.ReadResolutionScope();
631                                 records[i].TypeName = mr.ReadStringIndex();
632                                 records[i].TypeNameSpace = mr.ReadStringIndex();
633                         }
634                 }
635
636                 internal override void Write(MetadataWriter mw)
637                 {
638                         for (int i = 0; i < rowCount; i++)
639                         {
640                                 mw.WriteResolutionScope(records[i].ResolutionScope);
641                                 mw.WriteStringIndex(records[i].TypeName);
642                                 mw.WriteStringIndex(records[i].TypeNameSpace);
643                         }
644                 }
645
646                 protected override int GetRowSize(RowSizeCalc rsc)
647                 {
648                         return rsc
649                                 .WriteResolutionScope()
650                                 .WriteStringIndex()
651                                 .WriteStringIndex()
652                                 .Value;
653                 }
654
655                 internal void Fixup(ModuleBuilder moduleBuilder)
656                 {
657                         for (int i = 0; i < rowCount; i++)
658                         {
659                                 moduleBuilder.FixupPseudoToken(ref records[i].ResolutionScope);
660                         }
661                 }
662         }
663
664         sealed class TypeDefTable : Table<TypeDefTable.Record>
665         {
666                 internal const int Index = 0x02;
667
668                 internal struct Record
669                 {
670                         internal int Flags;
671                         internal int TypeName;
672                         internal int TypeNamespace;
673                         internal int Extends;
674                         internal int FieldList;
675                         internal int MethodList;
676                 }
677
678                 internal override void Read(MetadataReader mr)
679                 {
680                         for (int i = 0; i < records.Length; i++)
681                         {
682                                 records[i].Flags = mr.ReadInt32();
683                                 records[i].TypeName = mr.ReadStringIndex();
684                                 records[i].TypeNamespace = mr.ReadStringIndex();
685                                 records[i].Extends = mr.ReadTypeDefOrRef();
686                                 records[i].FieldList = mr.ReadField();
687                                 records[i].MethodList = mr.ReadMethodDef();
688                         }
689                 }
690
691                 internal override void Write(MetadataWriter mw)
692                 {
693                         mw.ModuleBuilder.WriteTypeDefTable(mw);
694                 }
695
696                 internal int AllocToken()
697                 {
698                         return 0x02000000 + AddVirtualRecord();
699                 }
700
701                 protected override int GetRowSize(RowSizeCalc rsc)
702                 {
703                         return rsc
704                                 .AddFixed(4)
705                                 .WriteStringIndex()
706                                 .WriteStringIndex()
707                                 .WriteTypeDefOrRef()
708                                 .WriteField()
709                                 .WriteMethodDef()
710                                 .Value;
711                 }
712         }
713
714         sealed class FieldPtrTable : Table<int>
715         {
716                 internal const int Index = 0x03;
717
718                 internal override void Read(MetadataReader mr)
719                 {
720                         for (int i = 0; i < records.Length; i++)
721                         {
722                                 records[i] = mr.ReadField();
723                         }
724                 }
725         }
726
727         sealed class FieldTable : Table<FieldTable.Record>
728         {
729                 internal const int Index = 0x04;
730
731                 internal struct Record
732                 {
733                         internal short Flags;
734                         internal int Name;
735                         internal int Signature;
736                 }
737
738                 internal override void Read(MetadataReader mr)
739                 {
740                         for (int i = 0; i < records.Length; i++)
741                         {
742                                 records[i].Flags = mr.ReadInt16();
743                                 records[i].Name = mr.ReadStringIndex();
744                                 records[i].Signature = mr.ReadBlobIndex();
745                         }
746                 }
747
748                 internal override void Write(MetadataWriter mw)
749                 {
750                         mw.ModuleBuilder.WriteFieldTable(mw);
751                 }
752
753                 protected override int GetRowSize(RowSizeCalc rsc)
754                 {
755                         return rsc
756                                 .AddFixed(2)
757                                 .WriteStringIndex()
758                                 .WriteBlobIndex()
759                                 .Value;
760                 }
761         }
762
763         sealed class MethodPtrTable : Table<int>
764         {
765                 internal const int Index = 0x05;
766
767                 internal override void Read(MetadataReader mr)
768                 {
769                         for (int i = 0; i < records.Length; i++)
770                         {
771                                 records[i] = mr.ReadMethodDef();
772                         }
773                 }
774         }
775
776         sealed class MethodDefTable : Table<MethodDefTable.Record>
777         {
778                 internal const int Index = 0x06;
779                 private int baseRVA;
780
781                 internal struct Record
782                 {
783                         internal int RVA;
784                         internal short ImplFlags;
785                         internal short Flags;
786                         internal int Name;
787                         internal int Signature;
788                         internal int ParamList;
789                 }
790
791                 internal override void Read(MetadataReader mr)
792                 {
793                         for (int i = 0; i < records.Length; i++)
794                         {
795                                 records[i].RVA = mr.ReadInt32();
796                                 records[i].ImplFlags = mr.ReadInt16();
797                                 records[i].Flags = mr.ReadInt16();
798                                 records[i].Name = mr.ReadStringIndex();
799                                 records[i].Signature = mr.ReadBlobIndex();
800                                 records[i].ParamList = mr.ReadParam();
801                         }
802                 }
803
804                 internal override void Write(MetadataWriter mw)
805                 {
806                         mw.ModuleBuilder.WriteMethodDefTable(baseRVA, mw);
807                 }
808
809                 protected override int GetRowSize(RowSizeCalc rsc)
810                 {
811                         return rsc
812                                 .AddFixed(8)
813                                 .WriteStringIndex()
814                                 .WriteBlobIndex()
815                                 .WriteParam()
816                                 .Value;
817                 }
818
819                 internal void Fixup(TextSection code)
820                 {
821                         baseRVA = (int)code.MethodBodiesRVA;
822                 }
823         }
824
825         sealed class ParamPtrTable : Table<int>
826         {
827                 internal const int Index = 0x07;
828
829                 internal override void Read(MetadataReader mr)
830                 {
831                         for (int i = 0; i < records.Length; i++)
832                         {
833                                 records[i] = mr.ReadParam();
834                         }
835                 }
836         }
837
838         sealed class ParamTable : Table<ParamTable.Record>
839         {
840                 internal const int Index = 0x08;
841
842                 internal struct Record
843                 {
844                         internal short Flags;
845                         internal short Sequence;
846                         internal int Name;
847                 }
848
849                 internal override void Read(MetadataReader mr)
850                 {
851                         for (int i = 0; i < records.Length; i++)
852                         {
853                                 records[i].Flags = mr.ReadInt16();
854                                 records[i].Sequence = mr.ReadInt16();
855                                 records[i].Name = mr.ReadStringIndex();
856                         }
857                 }
858
859                 internal override void Write(MetadataWriter mw)
860                 {
861                         mw.ModuleBuilder.WriteParamTable(mw);
862                 }
863
864                 protected override int GetRowSize(RowSizeCalc rsc)
865                 {
866                         return rsc
867                                 .AddFixed(4)
868                                 .WriteStringIndex()
869                                 .Value;
870                 }
871         }
872
873         sealed class InterfaceImplTable : SortedTable<InterfaceImplTable.Record>
874         {
875                 internal const int Index = 0x09;
876
877                 internal struct Record : IRecord
878                 {
879                         internal int Class;
880                         internal int Interface;
881
882                         int IRecord.SortKey
883                         {
884                                 get { return Class; }
885                         }
886
887                         int IRecord.FilterKey
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 : IRecord
1017                 {
1018                         internal short Type;
1019                         internal int Parent;
1020                         internal int Value;
1021
1022                         int IRecord.SortKey
1023                         {
1024                                 get { return EncodeHasConstant(Parent); }
1025                         }
1026
1027                         int IRecord.FilterKey
1028                         {
1029                                 get { return Parent; }
1030                         }
1031                 }
1032
1033                 internal override void Read(MetadataReader mr)
1034                 {
1035                         for (int i = 0; i < records.Length; i++)
1036                         {
1037                                 records[i].Type = mr.ReadInt16();
1038                                 records[i].Parent = mr.ReadHasConstant();
1039                                 records[i].Value = mr.ReadBlobIndex();
1040                         }
1041                 }
1042
1043                 internal override void Write(MetadataWriter mw)
1044                 {
1045                         for (int i = 0; i < rowCount; i++)
1046                         {
1047                                 mw.Write(records[i].Type);
1048                                 mw.WriteHasConstant(records[i].Parent);
1049                                 mw.WriteBlobIndex(records[i].Value);
1050                         }
1051                 }
1052
1053                 protected override int GetRowSize(RowSizeCalc rsc)
1054                 {
1055                         return rsc
1056                                 .AddFixed(2)
1057                                 .WriteHasConstant()
1058                                 .WriteBlobIndex()
1059                                 .Value;
1060                 }
1061
1062                 internal void Fixup(ModuleBuilder moduleBuilder)
1063                 {
1064                         for (int i = 0; i < rowCount; i++)
1065                         {
1066                                 moduleBuilder.FixupPseudoToken(ref records[i].Parent);
1067                         }
1068                         Sort();
1069                 }
1070
1071                 internal static int EncodeHasConstant(int token)
1072                 {
1073                         switch (token >> 24)
1074                         {
1075                                 case FieldTable.Index:
1076                                         return (token & 0xFFFFFF) << 2 | 0;
1077                                 case ParamTable.Index:
1078                                         return (token & 0xFFFFFF) << 2 | 1;
1079                                 case PropertyTable.Index:
1080                                         return (token & 0xFFFFFF) << 2 | 2;
1081                                 default:
1082                                         throw new InvalidOperationException();
1083                         }
1084                 }
1085
1086                 internal object GetRawConstantValue(Module module, int parent)
1087                 {
1088                         foreach (int i in Filter(parent))
1089                         {
1090                                 ByteReader br = module.GetBlob(module.Constant.records[i].Value);
1091                                 switch (module.Constant.records[i].Type)
1092                                 {
1093                                         // see ModuleBuilder.AddConstant for the encodings
1094                                         case Signature.ELEMENT_TYPE_BOOLEAN:
1095                                                 return br.ReadByte() != 0;
1096                                         case Signature.ELEMENT_TYPE_I1:
1097                                                 return br.ReadSByte();
1098                                         case Signature.ELEMENT_TYPE_I2:
1099                                                 return br.ReadInt16();
1100                                         case Signature.ELEMENT_TYPE_I4:
1101                                                 return br.ReadInt32();
1102                                         case Signature.ELEMENT_TYPE_I8:
1103                                                 return br.ReadInt64();
1104                                         case Signature.ELEMENT_TYPE_U1:
1105                                                 return br.ReadByte();
1106                                         case Signature.ELEMENT_TYPE_U2:
1107                                                 return br.ReadUInt16();
1108                                         case Signature.ELEMENT_TYPE_U4:
1109                                                 return br.ReadUInt32();
1110                                         case Signature.ELEMENT_TYPE_U8:
1111                                                 return br.ReadUInt64();
1112                                         case Signature.ELEMENT_TYPE_R4:
1113                                                 return br.ReadSingle();
1114                                         case Signature.ELEMENT_TYPE_R8:
1115                                                 return br.ReadDouble();
1116                                         case Signature.ELEMENT_TYPE_CHAR:
1117                                                 return br.ReadChar();
1118                                         case Signature.ELEMENT_TYPE_STRING:
1119                                                 {
1120                                                         char[] chars = new char[br.Length / 2];
1121                                                         for (int j = 0; j < chars.Length; j++)
1122                                                         {
1123                                                                 chars[j] = br.ReadChar();
1124                                                         }
1125                                                         return new String(chars);
1126                                                 }
1127                                         case Signature.ELEMENT_TYPE_CLASS:
1128                                                 if (br.ReadInt32() != 0)
1129                                                 {
1130                                                         throw new BadImageFormatException();
1131                                                 }
1132                                                 return null;
1133                                         default:
1134                                                 throw new BadImageFormatException();
1135                                 }
1136                         }
1137                         throw new InvalidOperationException();
1138                 }
1139         }
1140
1141         sealed class CustomAttributeTable : SortedTable<CustomAttributeTable.Record>
1142         {
1143                 internal const int Index = 0x0C;
1144
1145                 internal struct Record : IRecord
1146                 {
1147                         internal int Parent;
1148                         internal int Type;
1149                         internal int Value;
1150
1151                         int IRecord.SortKey
1152                         {
1153                                 get { return EncodeHasCustomAttribute(Parent); }
1154                         }
1155
1156                         int IRecord.FilterKey
1157                         {
1158                                 get { return Parent; }
1159                         }
1160                 }
1161
1162                 internal override void Read(MetadataReader mr)
1163                 {
1164                         for (int i = 0; i < records.Length; i++)
1165                         {
1166                                 records[i].Parent = mr.ReadHasCustomAttribute();
1167                                 records[i].Type = mr.ReadCustomAttributeType();
1168                                 records[i].Value = mr.ReadBlobIndex();
1169                         }
1170                 }
1171
1172                 internal override void Write(MetadataWriter mw)
1173                 {
1174                         for (int i = 0; i < rowCount; i++)
1175                         {
1176                                 mw.WriteHasCustomAttribute(records[i].Parent);
1177                                 mw.WriteCustomAttributeType(records[i].Type);
1178                                 mw.WriteBlobIndex(records[i].Value);
1179                         }
1180                 }
1181
1182                 protected override int GetRowSize(RowSizeCalc rsc)
1183                 {
1184                         return rsc
1185                                 .WriteHasCustomAttribute()
1186                                 .WriteCustomAttributeType()
1187                                 .WriteBlobIndex()
1188                                 .Value;
1189                 }
1190
1191                 internal void Fixup(ModuleBuilder moduleBuilder)
1192                 {
1193                         int[] genericParamFixup = moduleBuilder.GenericParam.GetIndexFixup();
1194                         for (int i = 0; i < rowCount; i++)
1195                         {
1196                                 moduleBuilder.FixupPseudoToken(ref records[i].Type);
1197                                 moduleBuilder.FixupPseudoToken(ref records[i].Parent);
1198                                 if (records[i].Parent >> 24 == GenericParamTable.Index)
1199                                 {
1200                                         records[i].Parent = (GenericParamTable.Index << 24) + genericParamFixup[(records[i].Parent & 0xFFFFFF) - 1] + 1;
1201                                 }
1202                         }
1203                         Sort();
1204                 }
1205
1206                 internal static int EncodeHasCustomAttribute(int token)
1207                 {
1208                         switch (token >> 24)
1209                         {
1210                                 case MethodDefTable.Index:
1211                                         return (token & 0xFFFFFF) << 5 | 0;
1212                                 case FieldTable.Index:
1213                                         return (token & 0xFFFFFF) << 5 | 1;
1214                                 case TypeRefTable.Index:
1215                                         return (token & 0xFFFFFF) << 5 | 2;
1216                                 case TypeDefTable.Index:
1217                                         return (token & 0xFFFFFF) << 5 | 3;
1218                                 case ParamTable.Index:
1219                                         return (token & 0xFFFFFF) << 5 | 4;
1220                                 case InterfaceImplTable.Index:
1221                                         return (token & 0xFFFFFF) << 5 | 5;
1222                                 case MemberRefTable.Index:
1223                                         return (token & 0xFFFFFF) << 5 | 6;
1224                                 case ModuleTable.Index:
1225                                         return (token & 0xFFFFFF) << 5 | 7;
1226                                 // Permission (8) table doesn't exist in the spec
1227                                 case PropertyTable.Index:
1228                                         return (token & 0xFFFFFF) << 5 | 9;
1229                                 case EventTable.Index:
1230                                         return (token & 0xFFFFFF) << 5 | 10;
1231                                 case StandAloneSigTable.Index:
1232                                         return (token & 0xFFFFFF) << 5 | 11;
1233                                 case ModuleRefTable.Index:
1234                                         return (token & 0xFFFFFF) << 5 | 12;
1235                                 case TypeSpecTable.Index:
1236                                         return (token & 0xFFFFFF) << 5 | 13;
1237                                 case AssemblyTable.Index:
1238                                         return (token & 0xFFFFFF) << 5 | 14;
1239                                 case AssemblyRefTable.Index:
1240                                         return (token & 0xFFFFFF) << 5 | 15;
1241                                 case FileTable.Index:
1242                                         return (token & 0xFFFFFF) << 5 | 16;
1243                                 case ExportedTypeTable.Index:
1244                                         return (token & 0xFFFFFF) << 5 | 17;
1245                                 case ManifestResourceTable.Index:
1246                                         return (token & 0xFFFFFF) << 5 | 18;
1247                                 case GenericParamTable.Index:
1248                                         return (token & 0xFFFFFF) << 5 | 19;
1249                                 default:
1250                                         throw new InvalidOperationException();
1251                         }
1252                 }
1253         }
1254
1255         sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>
1256         {
1257                 internal const int Index = 0x0D;
1258
1259                 internal struct Record : IRecord
1260                 {
1261                         internal int Parent;
1262                         internal int NativeType;
1263
1264                         int IRecord.SortKey
1265                         {
1266                                 get { return EncodeHasFieldMarshal(Parent); }
1267                         }
1268
1269                         int IRecord.FilterKey
1270                         {
1271                                 get { return Parent; }
1272                         }
1273                 }
1274
1275                 internal override void Read(MetadataReader mr)
1276                 {
1277                         for (int i = 0; i < records.Length; i++)
1278                         {
1279                                 records[i].Parent = mr.ReadHasFieldMarshal();
1280                                 records[i].NativeType = mr.ReadBlobIndex();
1281                         }
1282                 }
1283
1284                 internal override void Write(MetadataWriter mw)
1285                 {
1286                         for (int i = 0; i < rowCount; i++)
1287                         {
1288                                 mw.WriteHasFieldMarshal(records[i].Parent);
1289                                 mw.WriteBlobIndex(records[i].NativeType);
1290                         }
1291                 }
1292
1293                 protected override int GetRowSize(RowSizeCalc rsc)
1294                 {
1295                         return rsc
1296                                 .WriteHasFieldMarshal()
1297                                 .WriteBlobIndex()
1298                                 .Value;
1299                 }
1300
1301                 internal void Fixup(ModuleBuilder moduleBuilder)
1302                 {
1303                         for (int i = 0; i < rowCount; i++)
1304                         {
1305                                 records[i].Parent = moduleBuilder.ResolvePseudoToken(records[i].Parent);
1306                         }
1307                         Sort();
1308                 }
1309
1310                 internal static int EncodeHasFieldMarshal(int token)
1311                 {
1312                         switch (token >> 24)
1313                         {
1314                                 case FieldTable.Index:
1315                                         return (token & 0xFFFFFF) << 1 | 0;
1316                                 case ParamTable.Index:
1317                                         return (token & 0xFFFFFF) << 1 | 1;
1318                                 default:
1319                                         throw new InvalidOperationException();
1320                         }
1321                 }
1322         }
1323
1324         sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>
1325         {
1326                 internal const int Index = 0x0E;
1327
1328                 internal struct Record : IRecord
1329                 {
1330                         internal short Action;
1331                         internal int Parent;
1332                         internal int PermissionSet;
1333
1334                         int IRecord.SortKey
1335                         {
1336                                 get { return Parent; }
1337                         }
1338
1339                         int IRecord.FilterKey
1340                         {
1341                                 get { return Parent; }
1342                         }
1343                 }
1344
1345                 internal override void Read(MetadataReader mr)
1346                 {
1347                         for (int i = 0; i < records.Length; i++)
1348                         {
1349                                 records[i].Action = mr.ReadInt16();
1350                                 records[i].Parent = mr.ReadHasDeclSecurity();
1351                                 records[i].PermissionSet = mr.ReadBlobIndex();
1352                         }
1353                 }
1354
1355                 internal override void Write(MetadataWriter mw)
1356                 {
1357                         for (int i = 0; i < rowCount; i++)
1358                         {
1359                                 mw.Write(records[i].Action);
1360                                 mw.WriteHasDeclSecurity(records[i].Parent);
1361                                 mw.WriteBlobIndex(records[i].PermissionSet);
1362                         }
1363                 }
1364
1365                 protected override int GetRowSize(RowSizeCalc rsc)
1366                 {
1367                         return rsc
1368                                 .AddFixed(2)
1369                                 .WriteHasDeclSecurity()
1370                                 .WriteBlobIndex()
1371                                 .Value;
1372                 }
1373
1374                 internal void Fixup(ModuleBuilder moduleBuilder)
1375                 {
1376                         for (int i = 0; i < rowCount; i++)
1377                         {
1378                                 int token = records[i].Parent;
1379                                 moduleBuilder.FixupPseudoToken(ref token);
1380                                 // do the HasDeclSecurity encoding, so that we can sort the table
1381                                 switch (token >> 24)
1382                                 {
1383                                         case TypeDefTable.Index:
1384                                                 token = (token & 0xFFFFFF) << 2 | 0;
1385                                                 break;
1386                                         case MethodDefTable.Index:
1387                                                 token = (token & 0xFFFFFF) << 2 | 1;
1388                                                 break;
1389                                         case AssemblyTable.Index:
1390                                                 token = (token & 0xFFFFFF) << 2 | 2;
1391                                                 break;
1392                                         default:
1393                                                 throw new InvalidOperationException();
1394                                 }
1395                                 records[i].Parent = token;
1396                         }
1397                         Sort();
1398                 }
1399         }
1400
1401         sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>
1402         {
1403                 internal const int Index = 0x0f;
1404
1405                 internal struct Record : IRecord
1406                 {
1407                         internal short PackingSize;
1408                         internal int ClassSize;
1409                         internal int Parent;
1410
1411                         int IRecord.SortKey
1412                         {
1413                                 get { return Parent; }
1414                         }
1415
1416                         int IRecord.FilterKey
1417                         {
1418                                 get { return Parent; }
1419                         }
1420                 }
1421
1422                 internal override void Read(MetadataReader mr)
1423                 {
1424                         for (int i = 0; i < records.Length; i++)
1425                         {
1426                                 records[i].PackingSize = mr.ReadInt16();
1427                                 records[i].ClassSize = mr.ReadInt32();
1428                                 records[i].Parent = mr.ReadTypeDef();
1429                         }
1430                 }
1431
1432                 internal override void Write(MetadataWriter mw)
1433                 {
1434                         Sort();
1435                         for (int i = 0; i < rowCount; i++)
1436                         {
1437                                 mw.Write(records[i].PackingSize);
1438                                 mw.Write(records[i].ClassSize);
1439                                 mw.WriteTypeDef(records[i].Parent);
1440                         }
1441                 }
1442
1443                 protected override int GetRowSize(RowSizeCalc rsc)
1444                 {
1445                         return rsc
1446                                 .AddFixed(6)
1447                                 .WriteTypeDef()
1448                                 .Value;
1449                 }
1450         }
1451
1452         sealed class FieldLayoutTable : SortedTable<FieldLayoutTable.Record>
1453         {
1454                 internal const int Index = 0x10;
1455
1456                 internal struct Record : IRecord
1457                 {
1458                         internal int Offset;
1459                         internal int Field;
1460
1461                         int IRecord.SortKey
1462                         {
1463                                 get { return Field; }
1464                         }
1465
1466                         int IRecord.FilterKey
1467                         {
1468                                 get { return Field; }
1469                         }
1470                 }
1471
1472                 internal override void Read(MetadataReader mr)
1473                 {
1474                         for (int i = 0; i < records.Length; i++)
1475                         {
1476                                 records[i].Offset = mr.ReadInt32();
1477                                 records[i].Field = mr.ReadField();
1478                         }
1479                 }
1480
1481                 internal override void Write(MetadataWriter mw)
1482                 {
1483                         for (int i = 0; i < rowCount; i++)
1484                         {
1485                                 mw.Write(records[i].Offset);
1486                                 mw.WriteField(records[i].Field);
1487                         }
1488                 }
1489
1490                 protected override int GetRowSize(RowSizeCalc rsc)
1491                 {
1492                         return rsc
1493                                 .AddFixed(4)
1494                                 .WriteField()
1495                                 .Value;
1496                 }
1497
1498                 internal void Fixup(ModuleBuilder moduleBuilder)
1499                 {
1500                         for (int i = 0; i < rowCount; i++)
1501                         {
1502                                 records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field) & 0xFFFFFF;
1503                         }
1504                         Sort();
1505                 }
1506         }
1507
1508         sealed class StandAloneSigTable : Table<int>
1509         {
1510                 internal const int Index = 0x11;
1511
1512                 internal override void Read(MetadataReader mr)
1513                 {
1514                         for (int i = 0; i < records.Length; i++)
1515                         {
1516                                 records[i] = mr.ReadBlobIndex();
1517                         }
1518                 }
1519
1520                 internal override void Write(MetadataWriter mw)
1521                 {
1522                         for (int i = 0; i < rowCount; i++)
1523                         {
1524                                 mw.WriteBlobIndex(records[i]);
1525                         }
1526                 }
1527
1528                 protected override int GetRowSize(Table.RowSizeCalc rsc)
1529                 {
1530                         return rsc.WriteBlobIndex().Value;
1531                 }
1532
1533                 internal int FindOrAddRecord(int blob)
1534                 {
1535                         for (int i = 0; i < rowCount; i++)
1536                         {
1537                                 if (records[i] == blob)
1538                                 {
1539                                         return i + 1;
1540                                 }
1541                         }
1542                         return AddRecord(blob);
1543                 }
1544         }
1545
1546         sealed class EventMapTable : SortedTable<EventMapTable.Record>
1547         {
1548                 internal const int Index = 0x12;
1549
1550                 internal struct Record : IRecord
1551                 {
1552                         internal int Parent;
1553                         internal int EventList;
1554
1555                         int IRecord.SortKey
1556                         {
1557                                 get { return Parent; }
1558                         }
1559
1560                         int IRecord.FilterKey
1561                         {
1562                                 get { return Parent; }
1563                         }
1564                 }
1565
1566                 internal override void Read(MetadataReader mr)
1567                 {
1568                         for (int i = 0; i < records.Length; i++)
1569                         {
1570                                 records[i].Parent = mr.ReadTypeDef();
1571                                 records[i].EventList = mr.ReadEvent();
1572                         }
1573                 }
1574
1575                 internal override void Write(MetadataWriter mw)
1576                 {
1577                         for (int i = 0; i < rowCount; i++)
1578                         {
1579                                 mw.WriteTypeDef(records[i].Parent);
1580                                 mw.WriteEvent(records[i].EventList);
1581                         }
1582                 }
1583
1584                 protected override int GetRowSize(RowSizeCalc rsc)
1585                 {
1586                         return rsc
1587                                 .WriteTypeDef()
1588                                 .WriteEvent()
1589                                 .Value;
1590                 }
1591         }
1592
1593         sealed class EventPtrTable : Table<int>
1594         {
1595                 internal const int Index = 0x13;
1596
1597                 internal override void Read(MetadataReader mr)
1598                 {
1599                         for (int i = 0; i < records.Length; i++)
1600                         {
1601                                 records[i] = mr.ReadEvent();
1602                         }
1603                 }
1604         }
1605
1606         sealed class EventTable : Table<EventTable.Record>
1607         {
1608                 internal const int Index = 0x14;
1609
1610                 internal struct Record
1611                 {
1612                         internal short EventFlags;
1613                         internal int Name;
1614                         internal int EventType;
1615                 }
1616
1617                 internal override void Read(MetadataReader mr)
1618                 {
1619                         for (int i = 0; i < records.Length; i++)
1620                         {
1621                                 records[i].EventFlags = mr.ReadInt16();
1622                                 records[i].Name = mr.ReadStringIndex();
1623                                 records[i].EventType = mr.ReadTypeDefOrRef();
1624                         }
1625                 }
1626
1627                 internal override void Write(MetadataWriter mw)
1628                 {
1629                         for (int i = 0; i < rowCount; i++)
1630                         {
1631                                 mw.Write(records[i].EventFlags);
1632                                 mw.WriteStringIndex(records[i].Name);
1633                                 mw.WriteTypeDefOrRef(records[i].EventType);
1634                         }
1635                 }
1636
1637                 protected override int GetRowSize(RowSizeCalc rsc)
1638                 {
1639                         return rsc
1640                                 .AddFixed(2)
1641                                 .WriteStringIndex()
1642                                 .WriteTypeDefOrRef()
1643                                 .Value;
1644                 }
1645         }
1646
1647         sealed class PropertyMapTable : SortedTable<PropertyMapTable.Record>
1648         {
1649                 internal const int Index = 0x15;
1650
1651                 internal struct Record : IRecord
1652                 {
1653                         internal int Parent;
1654                         internal int PropertyList;
1655
1656                         int IRecord.SortKey
1657                         {
1658                                 get { return Parent; }
1659                         }
1660
1661                         int IRecord.FilterKey
1662                         {
1663                                 get { return Parent; }
1664                         }
1665                 }
1666
1667                 internal override void Read(MetadataReader mr)
1668                 {
1669                         for (int i = 0; i < records.Length; i++)
1670                         {
1671                                 records[i].Parent = mr.ReadTypeDef();
1672                                 records[i].PropertyList = mr.ReadProperty();
1673                         }
1674                 }
1675
1676                 internal override void Write(MetadataWriter mw)
1677                 {
1678                         for (int i = 0; i < rowCount; i++)
1679                         {
1680                                 mw.WriteTypeDef(records[i].Parent);
1681                                 mw.WriteProperty(records[i].PropertyList);
1682                         }
1683                 }
1684
1685                 protected override int GetRowSize(RowSizeCalc rsc)
1686                 {
1687                         return rsc
1688                                 .WriteTypeDef()
1689                                 .WriteProperty()
1690                                 .Value;
1691                 }
1692         }
1693
1694         sealed class PropertyPtrTable : Table<int>
1695         {
1696                 internal const int Index = 0x16;
1697
1698                 internal override void Read(MetadataReader mr)
1699                 {
1700                         for (int i = 0; i < records.Length; i++)
1701                         {
1702                                 records[i] = mr.ReadProperty();
1703                         }
1704                 }
1705         }
1706
1707         sealed class PropertyTable : Table<PropertyTable.Record>
1708         {
1709                 internal const int Index = 0x17;
1710
1711                 internal struct Record
1712                 {
1713                         internal short Flags;
1714                         internal int Name;
1715                         internal int Type;
1716                 }
1717
1718                 internal override void Read(MetadataReader mr)
1719                 {
1720                         for (int i = 0; i < records.Length; i++)
1721                         {
1722                                 records[i].Flags = mr.ReadInt16();
1723                                 records[i].Name = mr.ReadStringIndex();
1724                                 records[i].Type = mr.ReadBlobIndex();
1725                         }
1726                 }
1727
1728                 internal override void Write(MetadataWriter mw)
1729                 {
1730                         for (int i = 0; i < rowCount; i++)
1731                         {
1732                                 mw.Write(records[i].Flags);
1733                                 mw.WriteStringIndex(records[i].Name);
1734                                 mw.WriteBlobIndex(records[i].Type);
1735                         }
1736                 }
1737
1738                 protected override int GetRowSize(RowSizeCalc rsc)
1739                 {
1740                         return rsc
1741                                 .AddFixed(2)
1742                                 .WriteStringIndex()
1743                                 .WriteBlobIndex()
1744                                 .Value;
1745                 }
1746         }
1747
1748         sealed class MethodSemanticsTable : SortedTable<MethodSemanticsTable.Record>
1749         {
1750                 internal const int Index = 0x18;
1751
1752                 // semantics
1753                 internal const short Setter = 0x0001;
1754                 internal const short Getter = 0x0002;
1755                 internal const short Other = 0x0004;
1756                 internal const short AddOn = 0x0008;
1757                 internal const short RemoveOn = 0x0010;
1758                 internal const short Fire = 0x0020;
1759
1760                 internal struct Record : IRecord
1761                 {
1762                         internal short Semantics;
1763                         internal int Method;
1764                         internal int Association;
1765
1766                         int IRecord.SortKey
1767                         {
1768                                 get { return Association; }
1769                         }
1770
1771                         int IRecord.FilterKey
1772                         {
1773                                 get { return Association; }
1774                         }
1775                 }
1776
1777                 internal override void Read(MetadataReader mr)
1778                 {
1779                         for (int i = 0; i < records.Length; i++)
1780                         {
1781                                 records[i].Semantics = mr.ReadInt16();
1782                                 records[i].Method = mr.ReadMethodDef();
1783                                 records[i].Association = mr.ReadHasSemantics();
1784                         }
1785                 }
1786
1787                 internal override void Write(MetadataWriter mw)
1788                 {
1789                         for (int i = 0; i < rowCount; i++)
1790                         {
1791                                 mw.Write(records[i].Semantics);
1792                                 mw.WriteMethodDef(records[i].Method);
1793                                 mw.WriteHasSemantics(records[i].Association);
1794                         }
1795                 }
1796
1797                 protected override int GetRowSize(RowSizeCalc rsc)
1798                 {
1799                         return rsc
1800                                 .AddFixed(2)
1801                                 .WriteMethodDef()
1802                                 .WriteHasSemantics()
1803                                 .Value;
1804                 }
1805
1806                 internal void Fixup(ModuleBuilder moduleBuilder)
1807                 {
1808                         for (int i = 0; i < rowCount; i++)
1809                         {
1810                                 moduleBuilder.FixupPseudoToken(ref records[i].Method);
1811                                 int token = records[i].Association;
1812                                 // do the HasSemantics encoding, so that we can sort the table
1813                                 switch (token >> 24)
1814                                 {
1815                                         case EventTable.Index:
1816                                                 token = (token & 0xFFFFFF) << 1 | 0;
1817                                                 break;
1818                                         case PropertyTable.Index:
1819                                                 token = (token & 0xFFFFFF) << 1 | 1;
1820                                                 break;
1821                                         default:
1822                                                 throw new InvalidOperationException();
1823                                 }
1824                                 records[i].Association = token;
1825                         }
1826                         Sort();
1827                 }
1828
1829                 internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
1830                 {
1831                         foreach (int i in Filter(token))
1832                         {
1833                                 if ((records[i].Semantics & semantics) != 0)
1834                                 {
1835                                         MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1836                                         if (nonPublic || method.IsPublic)
1837                                         {
1838                                                 return (MethodInfo)method;
1839                                         }
1840                                 }
1841                         }
1842                         return null;
1843                 }
1844
1845                 internal MethodInfo[] GetMethods(Module module, int token, bool nonPublic, short semantics)
1846                 {
1847                         List<MethodInfo> methods = new List<MethodInfo>();
1848                         foreach (int i in Filter(token))
1849                         {
1850                                 if ((records[i].Semantics & semantics) != 0)
1851                                 {
1852                                         MethodInfo method = (MethodInfo)module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1853                                         if (nonPublic || method.IsPublic)
1854                                         {
1855                                                 methods.Add(method);
1856                                         }
1857                                 }
1858                         }
1859                         return methods.ToArray();
1860                 }
1861
1862                 internal void ComputeFlags(Module module, int token, out bool isPublic, out bool isNonPrivate, out bool isStatic)
1863                 {
1864                         isPublic = false;
1865                         isNonPrivate = false;
1866                         isStatic = false;
1867                         foreach (int i in Filter(token))
1868                         {
1869                                 MethodBase method = module.ResolveMethod((MethodDefTable.Index << 24) + records[i].Method);
1870                                 isPublic |= method.IsPublic;
1871                                 isNonPrivate |= (method.Attributes & MethodAttributes.MemberAccessMask) > MethodAttributes.Private;
1872                                 isStatic |= method.IsStatic;
1873                         }
1874                 }
1875         }
1876
1877         sealed class MethodImplTable : SortedTable<MethodImplTable.Record>
1878         {
1879                 internal const int Index = 0x19;
1880
1881                 internal struct Record : IRecord
1882                 {
1883                         internal int Class;
1884                         internal int MethodBody;
1885                         internal int MethodDeclaration;
1886
1887                         int IRecord.SortKey
1888                         {
1889                                 get { return Class; }
1890                         }
1891
1892                         int IRecord.FilterKey
1893                         {
1894                                 get { return Class; }
1895                         }
1896                 }
1897
1898                 internal override void Read(MetadataReader mr)
1899                 {
1900                         for (int i = 0; i < records.Length; i++)
1901                         {
1902                                 records[i].Class = mr.ReadTypeDef();
1903                                 records[i].MethodBody = mr.ReadMethodDefOrRef();
1904                                 records[i].MethodDeclaration = mr.ReadMethodDefOrRef();
1905                         }
1906                 }
1907
1908                 internal override void Write(MetadataWriter mw)
1909                 {
1910                         for (int i = 0; i < rowCount; i++)
1911                         {
1912                                 mw.WriteTypeDef(records[i].Class);
1913                                 mw.WriteMethodDefOrRef(records[i].MethodBody);
1914                                 mw.WriteMethodDefOrRef(records[i].MethodDeclaration);
1915                         }
1916                 }
1917
1918                 protected override int GetRowSize(RowSizeCalc rsc)
1919                 {
1920                         return rsc
1921                                 .WriteTypeDef()
1922                                 .WriteMethodDefOrRef()
1923                                 .WriteMethodDefOrRef()
1924                                 .Value;
1925                 }
1926
1927                 internal void Fixup(ModuleBuilder moduleBuilder)
1928                 {
1929                         for (int i = 0; i < rowCount; i++)
1930                         {
1931                                 moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
1932                                 moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
1933                         }
1934                         Sort();
1935                 }
1936         }
1937
1938         sealed class ModuleRefTable : Table<int>
1939         {
1940                 internal const int Index = 0x1A;
1941
1942                 internal override void Read(MetadataReader mr)
1943                 {
1944                         for (int i = 0; i < records.Length; i++)
1945                         {
1946                                 records[i] = mr.ReadStringIndex();
1947                         }
1948                 }
1949
1950                 internal override void Write(MetadataWriter mw)
1951                 {
1952                         for (int i = 0; i < rowCount; i++)
1953                         {
1954                                 mw.WriteStringIndex(records[i]);
1955                         }
1956                 }
1957
1958                 protected override int GetRowSize(RowSizeCalc rsc)
1959                 {
1960                         return rsc
1961                                 .WriteStringIndex()
1962                                 .Value;
1963                 }
1964
1965                 internal int FindOrAddRecord(int str)
1966                 {
1967                         for (int i = 0; i < rowCount; i++)
1968                         {
1969                                 if (records[i] == str)
1970                                 {
1971                                         return i + 1;
1972                                 }
1973                         }
1974                         return AddRecord(str);
1975                 }
1976         }
1977
1978         sealed class TypeSpecTable : Table<int>
1979         {
1980                 internal const int Index = 0x1B;
1981
1982                 internal override void Read(MetadataReader mr)
1983                 {
1984                         for (int i = 0; i < records.Length; i++)
1985                         {
1986                                 records[i] = mr.ReadBlobIndex();
1987                         }
1988                 }
1989
1990                 internal override void Write(MetadataWriter mw)
1991                 {
1992                         for (int i = 0; i < rowCount; i++)
1993                         {
1994                                 mw.WriteBlobIndex(records[i]);
1995                         }
1996                 }
1997
1998                 protected override int GetRowSize(Table.RowSizeCalc rsc)
1999                 {
2000                         return rsc.WriteBlobIndex().Value;
2001                 }
2002         }
2003
2004         sealed class ImplMapTable : SortedTable<ImplMapTable.Record>
2005         {
2006                 internal const int Index = 0x1C;
2007
2008                 internal struct Record : IRecord
2009                 {
2010                         internal short MappingFlags;
2011                         internal int MemberForwarded;
2012                         internal int ImportName;
2013                         internal int ImportScope;
2014
2015                         int IRecord.SortKey
2016                         {
2017                                 get { return MemberForwarded; }
2018                         }
2019
2020                         int IRecord.FilterKey
2021                         {
2022                                 get { return MemberForwarded; }
2023                         }
2024                 }
2025
2026                 internal override void Read(MetadataReader mr)
2027                 {
2028                         for (int i = 0; i < records.Length; i++)
2029                         {
2030                                 records[i].MappingFlags = mr.ReadInt16();
2031                                 records[i].MemberForwarded = mr.ReadMemberForwarded();
2032                                 records[i].ImportName = mr.ReadStringIndex();
2033                                 records[i].ImportScope = mr.ReadModuleRef();
2034                         }
2035                 }
2036
2037                 internal override void Write(MetadataWriter mw)
2038                 {
2039                         for (int i = 0; i < rowCount; i++)
2040                         {
2041                                 mw.Write(records[i].MappingFlags);
2042                                 mw.WriteMemberForwarded(records[i].MemberForwarded);
2043                                 mw.WriteStringIndex(records[i].ImportName);
2044                                 mw.WriteModuleRef(records[i].ImportScope);
2045                         }
2046                 }
2047
2048                 protected override int GetRowSize(RowSizeCalc rsc)
2049                 {
2050                         return rsc
2051                                 .AddFixed(2)
2052                                 .WriteMemberForwarded()
2053                                 .WriteStringIndex()
2054                                 .WriteModuleRef()
2055                                 .Value;
2056                 }
2057
2058                 internal void Fixup(ModuleBuilder moduleBuilder)
2059                 {
2060                         for (int i = 0; i < rowCount; i++)
2061                         {
2062                                 moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
2063                         }
2064                         Sort();
2065                 }
2066         }
2067
2068         sealed class FieldRVATable : SortedTable<FieldRVATable.Record>
2069         {
2070                 internal const int Index = 0x1D;
2071
2072                 internal struct Record : IRecord
2073                 {
2074                         internal int RVA;               // we set the high bit to signify that the RVA is in the CIL stream (instead of .sdata)
2075                         internal int Field;
2076
2077                         int IRecord.SortKey
2078                         {
2079                                 get { return Field; }
2080                         }
2081
2082                         int IRecord.FilterKey
2083                         {
2084                                 get { return Field; }
2085                         }
2086                 }
2087
2088                 internal override void Read(MetadataReader mr)
2089                 {
2090                         for (int i = 0; i < records.Length; i++)
2091                         {
2092                                 records[i].RVA = mr.ReadInt32();
2093                                 records[i].Field = mr.ReadField();
2094                         }
2095                 }
2096
2097                 internal override void Write(MetadataWriter mw)
2098                 {
2099                         for (int i = 0; i < rowCount; i++)
2100                         {
2101                                 mw.Write(records[i].RVA);
2102                                 mw.WriteField(records[i].Field);
2103                         }
2104                 }
2105
2106                 protected override int GetRowSize(RowSizeCalc rsc)
2107                 {
2108                         return rsc
2109                                 .AddFixed(4)
2110                                 .WriteField()
2111                                 .Value;
2112                 }
2113
2114                 internal void Fixup(ModuleBuilder moduleBuilder, int sdataRVA, int cilRVA)
2115                 {
2116                         for (int i = 0; i < rowCount; i++)
2117                         {
2118                                 if (records[i].RVA < 0)
2119                                 {
2120                                         records[i].RVA = (records[i].RVA & 0x7fffffff) + cilRVA;
2121                                 }
2122                                 else
2123                                 {
2124                                         records[i].RVA += sdataRVA;
2125                                 }
2126                                 moduleBuilder.FixupPseudoToken(ref records[i].Field);
2127                         }
2128                         Sort();
2129                 }
2130         }
2131
2132         sealed class AssemblyTable : Table<AssemblyTable.Record>
2133         {
2134                 internal const int Index = 0x20;
2135
2136                 internal struct Record
2137                 {
2138                         internal int HashAlgId;
2139                         internal ushort MajorVersion;
2140                         internal ushort MinorVersion;
2141                         internal ushort BuildNumber;
2142                         internal ushort RevisionNumber;
2143                         internal int Flags;
2144                         internal int PublicKey;
2145                         internal int Name;
2146                         internal int Culture;
2147                 }
2148
2149                 internal override void Read(MetadataReader mr)
2150                 {
2151                         for (int i = 0; i < records.Length; i++)
2152                         {
2153                                 records[i].HashAlgId = mr.ReadInt32();
2154                                 records[i].MajorVersion = mr.ReadUInt16();
2155                                 records[i].MinorVersion = mr.ReadUInt16();
2156                                 records[i].BuildNumber = mr.ReadUInt16();
2157                                 records[i].RevisionNumber = mr.ReadUInt16();
2158                                 records[i].Flags = mr.ReadInt32();
2159                                 records[i].PublicKey = mr.ReadBlobIndex();
2160                                 records[i].Name = mr.ReadStringIndex();
2161                                 records[i].Culture = mr.ReadStringIndex();
2162                         }
2163                 }
2164
2165                 internal override void Write(MetadataWriter mw)
2166                 {
2167                         for (int i = 0; i < rowCount; i++)
2168                         {
2169                                 mw.Write(records[i].HashAlgId);
2170                                 mw.Write(records[i].MajorVersion);
2171                                 mw.Write(records[i].MinorVersion);
2172                                 mw.Write(records[i].BuildNumber);
2173                                 mw.Write(records[i].RevisionNumber);
2174                                 mw.Write(records[i].Flags);
2175                                 mw.WriteBlobIndex(records[i].PublicKey);
2176                                 mw.WriteStringIndex(records[i].Name);
2177                                 mw.WriteStringIndex(records[i].Culture);
2178                         }
2179                 }
2180
2181                 protected override int GetRowSize(RowSizeCalc rsc)
2182                 {
2183                         return rsc
2184                                 .AddFixed(16)
2185                                 .WriteBlobIndex()
2186                                 .WriteStringIndex()
2187                                 .WriteStringIndex()
2188                                 .Value;
2189                 }
2190         }
2191
2192         sealed class AssemblyRefTable : Table<AssemblyRefTable.Record>
2193         {
2194                 internal const int Index = 0x23;
2195
2196                 internal struct Record
2197                 {
2198                         internal ushort MajorVersion;
2199                         internal ushort MinorVersion;
2200                         internal ushort BuildNumber;
2201                         internal ushort RevisionNumber;
2202                         internal int Flags;
2203                         internal int PublicKeyOrToken;
2204                         internal int Name;
2205                         internal int Culture;
2206                         internal int HashValue;
2207                 }
2208
2209                 internal int FindOrAddRecord(Record rec)
2210                 {
2211                         for (int i = 0; i < rowCount; i++)
2212                         {
2213                                 // note that we ignore HashValue here!
2214                                 if (records[i].Name == rec.Name
2215                                         && records[i].MajorVersion == rec.MajorVersion
2216                                         && records[i].MinorVersion == rec.MinorVersion
2217                                         && records[i].BuildNumber == rec.BuildNumber
2218                                         && records[i].RevisionNumber == rec.RevisionNumber
2219                                         && records[i].Flags == rec.Flags
2220                                         && records[i].PublicKeyOrToken == rec.PublicKeyOrToken
2221                                         && records[i].Culture == rec.Culture
2222                                         )
2223                                 {
2224                                         return i + 1;
2225                                 }
2226                         }
2227                         return AddRecord(rec);
2228                 }
2229
2230                 internal override void Read(MetadataReader mr)
2231                 {
2232                         for (int i = 0; i < records.Length; i++)
2233                         {
2234                                 records[i].MajorVersion = mr.ReadUInt16();
2235                                 records[i].MinorVersion = mr.ReadUInt16();
2236                                 records[i].BuildNumber = mr.ReadUInt16();
2237                                 records[i].RevisionNumber = mr.ReadUInt16();
2238                                 records[i].Flags = mr.ReadInt32();
2239                                 records[i].PublicKeyOrToken = mr.ReadBlobIndex();
2240                                 records[i].Name = mr.ReadStringIndex();
2241                                 records[i].Culture = mr.ReadStringIndex();
2242                                 records[i].HashValue = mr.ReadBlobIndex();
2243                         }
2244                 }
2245
2246                 internal override void Write(MetadataWriter mw)
2247                 {
2248                         for (int i = 0; i < rowCount; i++)
2249                         {
2250                                 mw.Write(records[i].MajorVersion);
2251                                 mw.Write(records[i].MinorVersion);
2252                                 mw.Write(records[i].BuildNumber);
2253                                 mw.Write(records[i].RevisionNumber);
2254                                 mw.Write(records[i].Flags);
2255                                 mw.WriteBlobIndex(records[i].PublicKeyOrToken);
2256                                 mw.WriteStringIndex(records[i].Name);
2257                                 mw.WriteStringIndex(records[i].Culture);
2258                                 mw.WriteBlobIndex(records[i].HashValue);
2259                         }
2260                 }
2261
2262                 protected override int GetRowSize(RowSizeCalc rsc)
2263                 {
2264                         return rsc
2265                                 .AddFixed(12)
2266                                 .WriteBlobIndex()
2267                                 .WriteStringIndex()
2268                                 .WriteStringIndex()
2269                                 .WriteBlobIndex()
2270                                 .Value;
2271                 }
2272         }
2273
2274         sealed class FileTable : Table<FileTable.Record>
2275         {
2276                 internal const int Index = 0x26;
2277
2278                 internal struct Record
2279                 {
2280                         internal int Flags;
2281                         internal int Name;
2282                         internal int HashValue;
2283                 }
2284
2285                 internal override void Read(MetadataReader mr)
2286                 {
2287                         for (int i = 0; i < records.Length; i++)
2288                         {
2289                                 records[i].Flags = mr.ReadInt32();
2290                                 records[i].Name = mr.ReadStringIndex();
2291                                 records[i].HashValue = mr.ReadBlobIndex();
2292                         }
2293                 }
2294
2295                 internal override void Write(MetadataWriter mw)
2296                 {
2297                         for (int i = 0; i < rowCount; i++)
2298                         {
2299                                 mw.Write(records[i].Flags);
2300                                 mw.WriteStringIndex(records[i].Name);
2301                                 mw.WriteBlobIndex(records[i].HashValue);
2302                         }
2303                 }
2304
2305                 protected override int GetRowSize(RowSizeCalc rsc)
2306                 {
2307                         return rsc
2308                                 .AddFixed(4)
2309                                 .WriteStringIndex()
2310                                 .WriteBlobIndex()
2311                                 .Value;
2312                 }
2313         }
2314
2315         sealed class ExportedTypeTable : Table<ExportedTypeTable.Record>
2316         {
2317                 internal const int Index = 0x27;
2318
2319                 internal struct Record
2320                 {
2321                         internal int Flags;
2322                         internal int TypeDefId;
2323                         internal int TypeName;
2324                         internal int TypeNamespace;
2325                         internal int Implementation;
2326                 }
2327
2328                 internal override void Read(MetadataReader mr)
2329                 {
2330                         for (int i = 0; i < records.Length; i++)
2331                         {
2332                                 records[i].Flags = mr.ReadInt32();
2333                                 records[i].TypeDefId = mr.ReadInt32();
2334                                 records[i].TypeName = mr.ReadStringIndex();
2335                                 records[i].TypeNamespace = mr.ReadStringIndex();
2336                                 records[i].Implementation = mr.ReadImplementation();
2337                         }
2338                 }
2339
2340                 internal override void Write(MetadataWriter mw)
2341                 {
2342                         for (int i = 0; i < rowCount; i++)
2343                         {
2344                                 mw.Write(records[i].Flags);
2345                                 mw.Write(records[i].TypeDefId);
2346                                 mw.WriteStringIndex(records[i].TypeName);
2347                                 mw.WriteStringIndex(records[i].TypeNamespace);
2348                                 mw.WriteImplementation(records[i].Implementation);
2349                         }
2350                 }
2351
2352                 protected override int GetRowSize(RowSizeCalc rsc)
2353                 {
2354                         return rsc
2355                                 .AddFixed(8)
2356                                 .WriteStringIndex()
2357                                 .WriteStringIndex()
2358                                 .WriteImplementation()
2359                                 .Value;
2360                 }
2361
2362                 internal int FindOrAddRecord(Record rec)
2363                 {
2364                         for (int i = 0; i < rowCount; i++)
2365                         {
2366                                 if (records[i].Implementation == rec.Implementation
2367                                         && records[i].TypeName == rec.TypeName
2368                                         && records[i].TypeNamespace == rec.TypeNamespace)
2369                                 {
2370                                         return i + 1;
2371                                 }
2372                         }
2373                         return AddRecord(rec);
2374                 }
2375
2376                 internal void Fixup(ModuleBuilder moduleBuilder)
2377                 {
2378                         for (int i = 0; i < rowCount; i++)
2379                         {
2380                                 moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
2381                         }
2382                 }
2383         }
2384
2385         sealed class ManifestResourceTable : Table<ManifestResourceTable.Record>
2386         {
2387                 internal const int Index = 0x28;
2388
2389                 internal struct Record
2390                 {
2391                         internal int Offset;
2392                         internal int Flags;
2393                         internal int Name;
2394                         internal int Implementation;
2395                 }
2396
2397                 internal override void Read(MetadataReader mr)
2398                 {
2399                         for (int i = 0; i < records.Length; i++)
2400                         {
2401                                 records[i].Offset = mr.ReadInt32();
2402                                 records[i].Flags = mr.ReadInt32();
2403                                 records[i].Name = mr.ReadStringIndex();
2404                                 records[i].Implementation = mr.ReadImplementation();
2405                         }
2406                 }
2407
2408                 internal override void Write(MetadataWriter mw)
2409                 {
2410                         for (int i = 0; i < rowCount; i++)
2411                         {
2412                                 mw.Write(records[i].Offset);
2413                                 mw.Write(records[i].Flags);
2414                                 mw.WriteStringIndex(records[i].Name);
2415                                 mw.WriteImplementation(records[i].Implementation);
2416                         }
2417                 }
2418
2419                 protected override int GetRowSize(RowSizeCalc rsc)
2420                 {
2421                         return rsc
2422                                 .AddFixed(8)
2423                                 .WriteStringIndex()
2424                                 .WriteImplementation()
2425                                 .Value;
2426                 }
2427
2428                 internal void Fixup(ModuleBuilder moduleBuilder)
2429                 {
2430                         for (int i = 0; i < rowCount; i++)
2431                         {
2432                                 moduleBuilder.FixupPseudoToken(ref records[i].Implementation);
2433                         }
2434                 }
2435         }
2436
2437         sealed class NestedClassTable : SortedTable<NestedClassTable.Record>
2438         {
2439                 internal const int Index = 0x29;
2440
2441                 internal struct Record : IRecord
2442                 {
2443                         internal int NestedClass;
2444                         internal int EnclosingClass;
2445
2446                         int IRecord.SortKey
2447                         {
2448                                 get { return NestedClass; }
2449                         }
2450
2451                         int IRecord.FilterKey
2452                         {
2453                                 get { return NestedClass; }
2454                         }
2455                 }
2456
2457                 internal override void Read(MetadataReader mr)
2458                 {
2459                         for (int i = 0; i < records.Length; i++)
2460                         {
2461                                 records[i].NestedClass = mr.ReadTypeDef();
2462                                 records[i].EnclosingClass = mr.ReadTypeDef();
2463                         }
2464                 }
2465
2466                 internal override void Write(MetadataWriter mw)
2467                 {
2468                         for (int i = 0; i < rowCount; i++)
2469                         {
2470                                 mw.WriteTypeDef(records[i].NestedClass);
2471                                 mw.WriteTypeDef(records[i].EnclosingClass);
2472                         }
2473                 }
2474
2475                 protected override int GetRowSize(RowSizeCalc rsc)
2476                 {
2477                         return rsc
2478                                 .WriteTypeDef()
2479                                 .WriteTypeDef()
2480                                 .Value;
2481                 }
2482
2483                 internal List<int> GetNestedClasses(int enclosingClass)
2484                 {
2485                         List<int> nestedClasses = new List<int>();
2486                         for (int i = 0; i < rowCount; i++)
2487                         {
2488                                 if (records[i].EnclosingClass == enclosingClass)
2489                                 {
2490                                         nestedClasses.Add(records[i].NestedClass);
2491                                 }
2492                         }
2493                         return nestedClasses;
2494                 }
2495         }
2496
2497         sealed class GenericParamTable : SortedTable<GenericParamTable.Record>, IComparer<GenericParamTable.Record>
2498         {
2499                 internal const int Index = 0x2A;
2500
2501                 internal struct Record : IRecord
2502                 {
2503                         internal short Number;
2504                         internal short Flags;
2505                         internal int Owner;
2506                         internal int Name;
2507                         // not part of the table, we use it to be able to fixup the GenericParamConstraint table
2508                         internal int unsortedIndex;
2509
2510                         int IRecord.SortKey
2511                         {
2512                                 get { return Owner; }
2513                         }
2514
2515                         int IRecord.FilterKey
2516                         {
2517                                 get { return Owner; }
2518                         }
2519                 }
2520
2521                 internal override void Read(MetadataReader mr)
2522                 {
2523                         for (int i = 0; i < records.Length; i++)
2524                         {
2525                                 records[i].Number = mr.ReadInt16();
2526                                 records[i].Flags = mr.ReadInt16();
2527                                 records[i].Owner = mr.ReadTypeOrMethodDef();
2528                                 records[i].Name = mr.ReadStringIndex();
2529                         }
2530                 }
2531
2532                 internal override void Write(MetadataWriter mw)
2533                 {
2534                         for (int i = 0; i < rowCount; i++)
2535                         {
2536                                 mw.Write(records[i].Number);
2537                                 mw.Write(records[i].Flags);
2538                                 mw.WriteTypeOrMethodDef(records[i].Owner);
2539                                 mw.WriteStringIndex(records[i].Name);
2540                         }
2541                 }
2542
2543                 protected override int GetRowSize(RowSizeCalc rsc)
2544                 {
2545                         return rsc
2546                                 .AddFixed(4)
2547                                 .WriteTypeOrMethodDef()
2548                                 .WriteStringIndex()
2549                                 .Value;
2550                 }
2551
2552                 internal void Fixup(ModuleBuilder moduleBuilder)
2553                 {
2554                         for (int i = 0; i < rowCount; i++)
2555                         {
2556                                 int token = records[i].Owner;
2557                                 moduleBuilder.FixupPseudoToken(ref token);
2558                                 // do the TypeOrMethodDef encoding, so that we can sort the table
2559                                 switch (token >> 24)
2560                                 {
2561                                         case TypeDefTable.Index:
2562                                                 records[i].Owner = (token & 0xFFFFFF) << 1 | 0;
2563                                                 break;
2564                                         case MethodDefTable.Index:
2565                                                 records[i].Owner = (token & 0xFFFFFF) << 1 | 1;
2566                                                 break;
2567                                         default:
2568                                                 throw new InvalidOperationException();
2569                                 }
2570                                 records[i].unsortedIndex = i;
2571                         }
2572                         // FXBUG the unnecessary (IComparer<Record>) cast is a workaround for a .NET 2.0 C# compiler bug
2573                         Array.Sort(records, 0, rowCount, (IComparer<Record>)this);
2574                 }
2575
2576                 int IComparer<Record>.Compare(Record x, Record y)
2577                 {
2578                         if (x.Owner == y.Owner)
2579                         {
2580                                 return x.Number == y.Number ? 0 : (x.Number > y.Number ? 1 : -1);
2581                         }
2582                         return x.Owner > y.Owner ? 1 : -1;
2583                 }
2584
2585                 internal void PatchAttribute(int token, GenericParameterAttributes genericParameterAttributes)
2586                 {
2587                         records[(token & 0xFFFFFF) - 1].Flags = (short)genericParameterAttributes;
2588                 }
2589
2590                 internal int[] GetIndexFixup()
2591                 {
2592                         int[] array = new int[rowCount];
2593                         for (int i = 0; i < rowCount; i++)
2594                         {
2595                                 array[records[i].unsortedIndex] = i;
2596                         }
2597                         return array;
2598                 }
2599
2600                 internal int FindFirstByOwner(int token)
2601                 {
2602                         foreach (int i in Filter(token))
2603                         {
2604                                 return i;
2605                         }
2606                         return -1;
2607                 }
2608         }
2609
2610         sealed class MethodSpecTable : Table<MethodSpecTable.Record>
2611         {
2612                 internal const int Index = 0x2B;
2613
2614                 internal struct Record
2615                 {
2616                         internal int Method;
2617                         internal int Instantiation;
2618                 }
2619
2620                 internal override void Read(MetadataReader mr)
2621                 {
2622                         for (int i = 0; i < records.Length; i++)
2623                         {
2624                                 records[i].Method = mr.ReadMethodDefOrRef();
2625                                 records[i].Instantiation = mr.ReadBlobIndex();
2626                         }
2627                 }
2628
2629                 internal override void Write(MetadataWriter mw)
2630                 {
2631                         for (int i = 0; i < rowCount; i++)
2632                         {
2633                                 mw.WriteMethodDefOrRef(records[i].Method);
2634                                 mw.WriteBlobIndex(records[i].Instantiation);
2635                         }
2636                 }
2637
2638                 protected override int GetRowSize(RowSizeCalc rsc)
2639                 {
2640                         return rsc
2641                                 .WriteMethodDefOrRef()
2642                                 .WriteBlobIndex()
2643                                 .Value;
2644                 }
2645
2646                 internal int FindOrAddRecord(Record record)
2647                 {
2648                         for (int i = 0; i < rowCount; i++)
2649                         {
2650                                 if (records[i].Method == record.Method
2651                                         && records[i].Instantiation == record.Instantiation)
2652                                 {
2653                                         return i + 1;
2654                                 }
2655                         }
2656                         return AddRecord(record);
2657                 }
2658
2659                 internal void Fixup(ModuleBuilder moduleBuilder)
2660                 {
2661                         for (int i = 0; i < rowCount; i++)
2662                         {
2663                                 moduleBuilder.FixupPseudoToken(ref records[i].Method);
2664                         }
2665                 }
2666         }
2667
2668         sealed class GenericParamConstraintTable : SortedTable<GenericParamConstraintTable.Record>
2669         {
2670                 internal const int Index = 0x2C;
2671
2672                 internal struct Record : IRecord
2673                 {
2674                         internal int Owner;
2675                         internal int Constraint;
2676
2677                         int IRecord.SortKey
2678                         {
2679                                 get { return Owner; }
2680                         }
2681
2682                         int IRecord.FilterKey
2683                         {
2684                                 get { return Owner; }
2685                         }
2686                 }
2687
2688                 internal override void Read(MetadataReader mr)
2689                 {
2690                         for (int i = 0; i < records.Length; i++)
2691                         {
2692                                 records[i].Owner = mr.ReadGenericParam();
2693                                 records[i].Constraint = mr.ReadTypeDefOrRef();
2694                         }
2695                 }
2696
2697                 internal override void Write(MetadataWriter mw)
2698                 {
2699                         for (int i = 0; i < rowCount; i++)
2700                         {
2701                                 mw.WriteGenericParam(records[i].Owner);
2702                                 mw.WriteTypeDefOrRef(records[i].Constraint);
2703                         }
2704                 }
2705
2706                 protected override int GetRowSize(RowSizeCalc rsc)
2707                 {
2708                         return rsc
2709                                 .WriteGenericParam()
2710                                 .WriteTypeDefOrRef()
2711                                 .Value;
2712                 }
2713
2714                 internal void Fixup(ModuleBuilder moduleBuilder)
2715                 {
2716                         int[] fixups = moduleBuilder.GenericParam.GetIndexFixup();
2717                         for (int i = 0; i < rowCount; i++)
2718                         {
2719                                 records[i].Owner = fixups[records[i].Owner - 1] + 1;
2720                         }
2721                         Sort();
2722                 }
2723         }
2724 }