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