do not check order sequence if option /order was not used
[mono.git] / mcs / class / IKVM.Reflection / Writer / MetadataWriter.cs
1 /*
2   Copyright (C) 2008 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.IO;
26 using System.Collections.Generic;
27 using System.Text;
28 using IKVM.Reflection.Emit;
29 using IKVM.Reflection.Metadata;
30
31 namespace IKVM.Reflection.Writer
32 {
33         sealed class MetadataWriter : MetadataRW
34         {
35                 private readonly ModuleBuilder moduleBuilder;
36                 private readonly Stream stream;
37                 private readonly byte[] buffer = new byte[8];
38
39                 internal MetadataWriter(ModuleBuilder module, Stream stream)
40                         : base(module, module.Strings.IsBig, module.Guids.IsBig, module.Blobs.IsBig)
41                 {
42                         this.moduleBuilder = module;
43                         this.stream = stream;
44                 }
45
46                 internal ModuleBuilder ModuleBuilder
47                 {
48                         get { return moduleBuilder; }
49                 }
50
51                 internal int Position
52                 {
53                         get { return (int)stream.Position; }
54                 }
55
56                 internal void Write(ByteBuffer bb)
57                 {
58                         bb.WriteTo(stream);
59                 }
60
61                 internal void Write(byte[] value)
62                 {
63                         stream.Write(value, 0, value.Length);
64                 }
65
66                 internal void Write(byte value)
67                 {
68                         stream.WriteByte(value);
69                 }
70
71                 internal void Write(ushort value)
72                 {
73                         Write((short)value);
74                 }
75
76                 internal void Write(short value)
77                 {
78                         stream.WriteByte((byte)value);
79                         stream.WriteByte((byte)(value >> 8));
80                 }
81
82                 internal void Write(uint value)
83                 {
84                         Write((int)value);
85                 }
86
87                 internal void Write(int value)
88                 {
89                         buffer[0] = (byte)value;
90                         buffer[1] = (byte)(value >> 8);
91                         buffer[2] = (byte)(value >> 16);
92                         buffer[3] = (byte)(value >> 24);
93                         stream.Write(buffer, 0, 4);
94                 }
95
96                 internal void Write(ulong value)
97                 {
98                         Write((long)value);
99                 }
100
101                 internal void Write(long value)
102                 {
103                         buffer[0] = (byte)value;
104                         buffer[1] = (byte)(value >> 8);
105                         buffer[2] = (byte)(value >> 16);
106                         buffer[3] = (byte)(value >> 24);
107                         buffer[4] = (byte)(value >> 32);
108                         buffer[5] = (byte)(value >> 40);
109                         buffer[6] = (byte)(value >> 48);
110                         buffer[7] = (byte)(value >> 56);
111                         stream.Write(buffer, 0, 8);
112                 }
113
114                 internal void WriteCompressedInt(int value)
115                 {
116                         if (value <= 0x7F)
117                         {
118                                 Write((byte)value);
119                         }
120                         else if (value <= 0x3FFF)
121                         {
122                                 Write((byte)(0x80 | (value >> 8)));
123                                 Write((byte)value);
124                         }
125                         else
126                         {
127                                 Write((byte)(0xC0 | (value >> 24)));
128                                 Write((byte)(value >> 16));
129                                 Write((byte)(value >> 8));
130                                 Write((byte)value);
131                         }
132                 }
133
134                 internal static int GetCompressedIntLength(int value)
135                 {
136                         if (value <= 0x7F)
137                         {
138                                 return 1;
139                         }
140                         else if (value <= 0x3FFF)
141                         {
142                                 return 2;
143                         }
144                         else
145                         {
146                                 return 4;
147                         }
148                 }
149
150                 internal void WriteStringIndex(int index)
151                 {
152                         if (bigStrings)
153                         {
154                                 Write(index);
155                         }
156                         else
157                         {
158                                 Write((short)index);
159                         }
160                 }
161
162                 internal void WriteGuidIndex(int index)
163                 {
164                         if (bigGuids)
165                         {
166                                 Write(index);
167                         }
168                         else
169                         {
170                                 Write((short)index);
171                         }
172                 }
173
174                 internal void WriteBlobIndex(int index)
175                 {
176                         if (bigBlobs)
177                         {
178                                 Write(index);
179                         }
180                         else
181                         {
182                                 Write((short)index);
183                         }
184                 }
185
186                 internal void WriteTypeDefOrRef(int token)
187                 {
188                         switch (token >> 24)
189                         {
190                                 case 0:
191                                         break;
192                                 case TypeDefTable.Index:
193                                         token = (token & 0xFFFFFF) << 2 | 0;
194                                         break;
195                                 case TypeRefTable.Index:
196                                         token = (token & 0xFFFFFF) << 2 | 1;
197                                         break;
198                                 case TypeSpecTable.Index:
199                                         token = (token & 0xFFFFFF) << 2 | 2;
200                                         break;
201                                 default:
202                                         throw new InvalidOperationException();
203                         }
204                         if (bigTypeDefOrRef)
205                         {
206                                 Write(token);
207                         }
208                         else
209                         {
210                                 Write((short)token);
211                         }
212                 }
213
214                 internal void WriteEncodedTypeDefOrRef(int encodedToken)
215                 {
216                         if (bigTypeDefOrRef)
217                         {
218                                 Write(encodedToken);
219                         }
220                         else
221                         {
222                                 Write((short)encodedToken);
223                         }
224                 }
225
226                 internal void WriteHasCustomAttribute(int token)
227                 {
228                         int encodedToken = CustomAttributeTable.EncodeHasCustomAttribute(token);
229                         if (bigHasCustomAttribute)
230                         {
231                                 Write(encodedToken);
232                         }
233                         else
234                         {
235                                 Write((short)encodedToken);
236                         }
237                 }
238
239                 internal void WriteCustomAttributeType(int token)
240                 {
241                         switch (token >> 24)
242                         {
243                                 case MethodDefTable.Index:
244                                         token = (token & 0xFFFFFF) << 3 | 2;
245                                         break;
246                                 case MemberRefTable.Index:
247                                         token = (token & 0xFFFFFF) << 3 | 3;
248                                         break;
249                                 default:
250                                         throw new InvalidOperationException();
251                         }
252                         if (bigCustomAttributeType)
253                         {
254                                 Write(token);
255                         }
256                         else
257                         {
258                                 Write((short)token);
259                         }
260                 }
261
262                 internal void WriteField(int index)
263                 {
264                         if (bigField)
265                         {
266                                 Write(index & 0xFFFFFF);
267                         }
268                         else
269                         {
270                                 Write((short)index);
271                         }
272                 }
273
274                 internal void WriteMethodDef(int index)
275                 {
276                         if (bigMethodDef)
277                         {
278                                 Write(index & 0xFFFFFF);
279                         }
280                         else
281                         {
282                                 Write((short)index);
283                         }
284                 }
285
286                 internal void WriteParam(int index)
287                 {
288                         if (bigParam)
289                         {
290                                 Write(index & 0xFFFFFF);
291                         }
292                         else
293                         {
294                                 Write((short)index);
295                         }
296                 }
297
298                 internal void WriteTypeDef(int index)
299                 {
300                         if (bigTypeDef)
301                         {
302                                 Write(index & 0xFFFFFF);
303                         }
304                         else
305                         {
306                                 Write((short)index);
307                         }
308                 }
309
310                 internal void WriteEvent(int index)
311                 {
312                         if (bigEvent)
313                         {
314                                 Write(index & 0xFFFFFF);
315                         }
316                         else
317                         {
318                                 Write((short)index);
319                         }
320                 }
321
322                 internal void WriteProperty(int index)
323                 {
324                         if (bigProperty)
325                         {
326                                 Write(index & 0xFFFFFF);
327                         }
328                         else
329                         {
330                                 Write((short)index);
331                         }
332                 }
333
334                 internal void WriteGenericParam(int index)
335                 {
336                         if (bigGenericParam)
337                         {
338                                 Write(index & 0xFFFFFF);
339                         }
340                         else
341                         {
342                                 Write((short)index);
343                         }
344                 }
345
346                 internal void WriteModuleRef(int index)
347                 {
348                         if (bigModuleRef)
349                         {
350                                 Write(index & 0xFFFFFF);
351                         }
352                         else
353                         {
354                                 Write((short)index);
355                         }
356                 }
357
358                 internal void WriteResolutionScope(int token)
359                 {
360                         switch (token >> 24)
361                         {
362                                 case ModuleTable.Index:
363                                         token = (token & 0xFFFFFF) << 2 | 0;
364                                         break;
365                                 case ModuleRefTable.Index:
366                                         token = (token & 0xFFFFFF) << 2 | 1;
367                                         break;
368                                 case AssemblyRefTable.Index:
369                                         token = (token & 0xFFFFFF) << 2 | 2;
370                                         break;
371                                 case TypeRefTable.Index:
372                                         token = (token & 0xFFFFFF) << 2 | 3;
373                                         break;
374                                 default:
375                                         throw new InvalidOperationException();
376                         }
377                         if (bigResolutionScope)
378                         {
379                                 Write(token);
380                         }
381                         else
382                         {
383                                 Write((short)token);
384                         }
385                 }
386
387                 internal void WriteMemberRefParent(int token)
388                 {
389                         switch (token >> 24)
390                         {
391                                 case TypeDefTable.Index:
392                                         token = (token & 0xFFFFFF) << 3 | 0;
393                                         break;
394                                 case TypeRefTable.Index:
395                                         token = (token & 0xFFFFFF) << 3 | 1;
396                                         break;
397                                 case ModuleRefTable.Index:
398                                         token = (token & 0xFFFFFF) << 3 | 2;
399                                         break;
400                                 case MethodDefTable.Index:
401                                         token = (token & 0xFFFFFF) << 3 | 3;
402                                         break;
403                                 case TypeSpecTable.Index:
404                                         token = (token & 0xFFFFFF) << 3 | 4;
405                                         break;
406                                 default:
407                                         throw new InvalidOperationException();
408                         }
409                         if (bigMemberRefParent)
410                         {
411                                 Write(token);
412                         }
413                         else
414                         {
415                                 Write((short)token);
416                         }
417                 }
418
419                 internal void WriteMethodDefOrRef(int token)
420                 {
421                         switch (token >> 24)
422                         {
423                                 case MethodDefTable.Index:
424                                         token = (token & 0xFFFFFF) << 1 | 0;
425                                         break;
426                                 case MemberRefTable.Index:
427                                         token = (token & 0xFFFFFF) << 1 | 1;
428                                         break;
429                                 default:
430                                         throw new InvalidOperationException();
431                         }
432                         if (bigMethodDefOrRef)
433                         {
434                                 Write(token);
435                         }
436                         else
437                         {
438                                 Write((short)token);
439                         }
440                 }
441
442                 internal void WriteHasConstant(int token)
443                 {
444                         int encodedToken = ConstantTable.EncodeHasConstant(token);
445                         if (bigHasConstant)
446                         {
447                                 Write(encodedToken);
448                         }
449                         else
450                         {
451                                 Write((short)encodedToken);
452                         }
453                 }
454
455                 internal void WriteHasSemantics(int encodedToken)
456                 {
457                         // NOTE because we've already had to do the encoding (to be able to sort the table)
458                         // here we simple write the value
459                         if (bigHasSemantics)
460                         {
461                                 Write(encodedToken);
462                         }
463                         else
464                         {
465                                 Write((short)encodedToken);
466                         }
467                 }
468
469                 internal void WriteImplementation(int token)
470                 {
471                         switch (token >> 24)
472                         {
473                                 case 0:
474                                         break;
475                                 case FileTable.Index:
476                                         token = (token & 0xFFFFFF) << 2 | 0;
477                                         break;
478                                 case AssemblyRefTable.Index:
479                                         token = (token & 0xFFFFFF) << 2 | 1;
480                                         break;
481                                 case ExportedTypeTable.Index:
482                                         token = (token & 0xFFFFFF) << 2 | 2;
483                                         break;
484                                 default:
485                                         throw new InvalidOperationException();
486                         }
487                         if (bigImplementation)
488                         {
489                                 Write(token);
490                         }
491                         else
492                         {
493                                 Write((short)token);
494                         }
495                 }
496
497                 internal void WriteTypeOrMethodDef(int encodedToken)
498                 {
499                         // NOTE because we've already had to do the encoding (to be able to sort the table)
500                         // here we simple write the value
501                         if (bigTypeOrMethodDef)
502                         {
503                                 Write(encodedToken);
504                         }
505                         else
506                         {
507                                 Write((short)encodedToken);
508                         }
509                 }
510
511                 internal void WriteHasDeclSecurity(int encodedToken)
512                 {
513                         // NOTE because we've already had to do the encoding (to be able to sort the table)
514                         // here we simple write the value
515                         if (bigHasDeclSecurity)
516                         {
517                                 Write(encodedToken);
518                         }
519                         else
520                         {
521                                 Write((short)encodedToken);
522                         }
523                 }
524
525                 internal void WriteMemberForwarded(int token)
526                 {
527                         switch (token >> 24)
528                         {
529                                 case FieldTable.Index:
530                                         token = (token & 0xFFFFFF) << 1 | 0;
531                                     break;
532                                 case MethodDefTable.Index:
533                                         token = (token & 0xFFFFFF) << 1 | 1;
534                                         break;
535                                 default:
536                                         throw new InvalidOperationException();
537                         }
538                         if (bigMemberForwarded)
539                         {
540                                 Write(token);
541                         }
542                         else
543                         {
544                                 Write((short)token);
545                         }
546                 }
547
548                 internal void WriteHasFieldMarshal(int token)
549                 {
550                         int encodedToken = FieldMarshalTable.EncodeHasFieldMarshal(token);
551                         if (bigHasFieldMarshal)
552                         {
553                                 Write(encodedToken);
554                         }
555                         else
556                         {
557                                 Write((short)encodedToken);
558                         }
559                 }
560         }
561 }