PageRenderTime 62ms CodeModel.GetById 15ms app.highlight 42ms RepoModel.GetById 2ms app.codeStats 0ms

/Mono.Cecil.Metadata/Utilities.cs

http://github.com/jbevain/cecil
C# | 650 lines | 628 code | 13 blank | 9 comment | 40 complexity | fe42e400a6fca96be9ee2674b5f4c5fa MD5 | raw file
  1//
  2// Author:
  3//   Jb Evain (jbevain@gmail.com)
  4//
  5// Copyright (c) 2008 - 2015 Jb Evain
  6// Copyright (c) 2008 - 2011 Novell, Inc.
  7//
  8// Licensed under the MIT/X11 license.
  9//
 10
 11using System;
 12
 13using Mono.Cecil.Metadata;
 14
 15namespace Mono.Cecil {
 16
 17	static partial class Mixin {
 18
 19		public const int TableCount = 58;
 20		public const int CodedIndexCount = 14;
 21
 22		public static uint ReadCompressedUInt32 (this byte [] data, ref int position)
 23		{
 24			uint integer;
 25			if ((data [position] & 0x80) == 0) {
 26				integer = data [position];
 27				position++;
 28			} else if ((data [position] & 0x40) == 0) {
 29				integer = (uint) (data [position] & ~0x80) << 8;
 30				integer |= data [position + 1];
 31				position += 2;
 32			} else {
 33				integer = (uint) (data [position] & ~0xc0) << 24;
 34				integer |= (uint) data [position + 1] << 16;
 35				integer |= (uint) data [position + 2] << 8;
 36				integer |= (uint) data [position + 3];
 37				position += 4;
 38			}
 39			return integer;
 40		}
 41
 42		public static MetadataToken GetMetadataToken (this CodedIndex self, uint data)
 43		{
 44			uint rid;
 45			TokenType token_type;
 46			switch (self) {
 47			case CodedIndex.TypeDefOrRef:
 48				rid = data >> 2;
 49				switch (data & 3) {
 50				case 0:
 51					token_type = TokenType.TypeDef; goto ret;
 52				case 1:
 53					token_type = TokenType.TypeRef; goto ret;
 54				case 2:
 55					token_type = TokenType.TypeSpec; goto ret;
 56				default:
 57					goto exit;
 58				}
 59			case CodedIndex.HasConstant:
 60				rid = data >> 2;
 61				switch (data & 3) {
 62				case 0:
 63					token_type = TokenType.Field; goto ret;
 64				case 1:
 65					token_type = TokenType.Param; goto ret;
 66				case 2:
 67					token_type = TokenType.Property; goto ret;
 68				default:
 69					goto exit;
 70				}
 71			case CodedIndex.HasCustomAttribute:
 72				rid = data >> 5;
 73				switch (data & 31) {
 74				case 0:
 75					token_type = TokenType.Method; goto ret;
 76				case 1:
 77					token_type = TokenType.Field; goto ret;
 78				case 2:
 79					token_type = TokenType.TypeRef; goto ret;
 80				case 3:
 81					token_type = TokenType.TypeDef; goto ret;
 82				case 4:
 83					token_type = TokenType.Param; goto ret;
 84				case 5:
 85					token_type = TokenType.InterfaceImpl; goto ret;
 86				case 6:
 87					token_type = TokenType.MemberRef; goto ret;
 88				case 7:
 89					token_type = TokenType.Module; goto ret;
 90				case 8:
 91					token_type = TokenType.Permission; goto ret;
 92				case 9:
 93					token_type = TokenType.Property; goto ret;
 94				case 10:
 95					token_type = TokenType.Event; goto ret;
 96				case 11:
 97					token_type = TokenType.Signature; goto ret;
 98				case 12:
 99					token_type = TokenType.ModuleRef; goto ret;
100				case 13:
101					token_type = TokenType.TypeSpec; goto ret;
102				case 14:
103					token_type = TokenType.Assembly; goto ret;
104				case 15:
105					token_type = TokenType.AssemblyRef; goto ret;
106				case 16:
107					token_type = TokenType.File; goto ret;
108				case 17:
109					token_type = TokenType.ExportedType; goto ret;
110				case 18:
111					token_type = TokenType.ManifestResource; goto ret;
112				case 19:
113					token_type = TokenType.GenericParam; goto ret;
114				case 20:
115					token_type = TokenType.GenericParamConstraint; goto ret;
116				case 21:
117					token_type = TokenType.MethodSpec; goto ret;
118				default:
119					goto exit;
120				}
121			case CodedIndex.HasFieldMarshal:
122				rid = data >> 1;
123				switch (data & 1) {
124				case 0:
125					token_type = TokenType.Field; goto ret;
126				case 1:
127					token_type = TokenType.Param; goto ret;
128				default:
129					goto exit;
130				}
131			case CodedIndex.HasDeclSecurity:
132				rid = data >> 2;
133				switch (data & 3) {
134				case 0:
135					token_type = TokenType.TypeDef; goto ret;
136				case 1:
137					token_type = TokenType.Method; goto ret;
138				case 2:
139					token_type = TokenType.Assembly; goto ret;
140				default:
141					goto exit;
142				}
143			case CodedIndex.MemberRefParent:
144				rid = data >> 3;
145				switch (data & 7) {
146				case 0:
147					token_type = TokenType.TypeDef; goto ret;
148				case 1:
149					token_type = TokenType.TypeRef; goto ret;
150				case 2:
151					token_type = TokenType.ModuleRef; goto ret;
152				case 3:
153					token_type = TokenType.Method; goto ret;
154				case 4:
155					token_type = TokenType.TypeSpec; goto ret;
156				default:
157					goto exit;
158				}
159			case CodedIndex.HasSemantics:
160				rid = data >> 1;
161				switch (data & 1) {
162				case 0:
163					token_type = TokenType.Event; goto ret;
164				case 1:
165					token_type = TokenType.Property; goto ret;
166				default:
167					goto exit;
168				}
169			case CodedIndex.MethodDefOrRef:
170				rid = data >> 1;
171				switch (data & 1) {
172				case 0:
173					token_type = TokenType.Method; goto ret;
174				case 1:
175					token_type = TokenType.MemberRef; goto ret;
176				default:
177					goto exit;
178				}
179			case CodedIndex.MemberForwarded:
180				rid = data >> 1;
181				switch (data & 1) {
182				case 0:
183					token_type = TokenType.Field; goto ret;
184				case 1:
185					token_type = TokenType.Method; goto ret;
186				default:
187					goto exit;
188				}
189			case CodedIndex.Implementation:
190				rid = data >> 2;
191				switch (data & 3) {
192				case 0:
193					token_type = TokenType.File; goto ret;
194				case 1:
195					token_type = TokenType.AssemblyRef; goto ret;
196				case 2:
197					token_type = TokenType.ExportedType; goto ret;
198				default:
199					goto exit;
200				}
201			case CodedIndex.CustomAttributeType:
202				rid = data >> 3;
203				switch (data & 7) {
204				case 2:
205					token_type = TokenType.Method; goto ret;
206				case 3:
207					token_type = TokenType.MemberRef; goto ret;
208				default:
209					goto exit;
210				}
211			case CodedIndex.ResolutionScope:
212				rid = data >> 2;
213				switch (data & 3) {
214				case 0:
215					token_type = TokenType.Module; goto ret;
216				case 1:
217					token_type = TokenType.ModuleRef; goto ret;
218				case 2:
219					token_type = TokenType.AssemblyRef; goto ret;
220				case 3:
221					token_type = TokenType.TypeRef; goto ret;
222				default:
223					goto exit;
224				}
225			case CodedIndex.TypeOrMethodDef:
226				rid = data >> 1;
227				switch (data & 1) {
228				case 0:
229					token_type = TokenType.TypeDef; goto ret;
230				case 1:
231					token_type = TokenType.Method; goto ret;
232				default: goto exit;
233				}
234			case CodedIndex.HasCustomDebugInformation:
235				rid = data >> 5;
236				switch (data & 31) {
237				case 0:
238					token_type = TokenType.Method; goto ret;
239				case 1:
240					token_type = TokenType.Field; goto ret;
241				case 2:
242					token_type = TokenType.TypeRef; goto ret;
243				case 3:
244					token_type = TokenType.TypeDef; goto ret;
245				case 4:
246					token_type = TokenType.Param; goto ret;
247				case 5:
248					token_type = TokenType.InterfaceImpl; goto ret;
249				case 6:
250					token_type = TokenType.MemberRef; goto ret;
251				case 7:
252					token_type = TokenType.Module; goto ret;
253				case 8:
254					token_type = TokenType.Permission; goto ret;
255				case 9:
256					token_type = TokenType.Property; goto ret;
257				case 10:
258					token_type = TokenType.Event; goto ret;
259				case 11:
260					token_type = TokenType.Signature; goto ret;
261				case 12:
262					token_type = TokenType.ModuleRef; goto ret;
263				case 13:
264					token_type = TokenType.TypeSpec; goto ret;
265				case 14:
266					token_type = TokenType.Assembly; goto ret;
267				case 15:
268					token_type = TokenType.AssemblyRef; goto ret;
269				case 16:
270					token_type = TokenType.File; goto ret;
271				case 17:
272					token_type = TokenType.ExportedType; goto ret;
273				case 18:
274					token_type = TokenType.ManifestResource; goto ret;
275				case 19:
276					token_type = TokenType.GenericParam; goto ret;
277				case 20:
278					token_type = TokenType.GenericParamConstraint; goto ret;
279				case 21:
280					token_type = TokenType.MethodSpec; goto ret;
281				case 22:
282					token_type = TokenType.Document; goto ret;
283				case 23:
284					token_type = TokenType.LocalScope; goto ret;
285				case 24:
286					token_type = TokenType.LocalVariable; goto ret;
287				case 25:
288					token_type = TokenType.LocalConstant; goto ret;
289				case 26:
290					token_type = TokenType.ImportScope; goto ret;
291				default:
292					goto exit;
293				}
294			default:
295				goto exit;
296			}
297		ret:
298			return new MetadataToken (token_type, rid);
299		exit:
300			return MetadataToken.Zero;
301		}
302
303		public static uint CompressMetadataToken (this CodedIndex self, MetadataToken token)
304		{
305			uint ret = 0;
306			if (token.RID == 0)
307				return ret;
308			switch (self) {
309			case CodedIndex.TypeDefOrRef:
310				ret = token.RID << 2;
311				switch (token.TokenType) {
312				case TokenType.TypeDef:
313					return ret | 0;
314				case TokenType.TypeRef:
315					return ret | 1;
316				case TokenType.TypeSpec:
317					return ret | 2;
318				default:
319					goto exit;
320				}
321			case CodedIndex.HasConstant:
322				ret = token.RID << 2;
323				switch (token.TokenType) {
324				case TokenType.Field:
325					return ret | 0;
326				case TokenType.Param:
327					return ret | 1;
328				case TokenType.Property:
329					return ret | 2;
330				default:
331					goto exit;
332				}
333			case CodedIndex.HasCustomAttribute:
334				ret = token.RID << 5;
335				switch (token.TokenType) {
336				case TokenType.Method:
337					return ret | 0;
338				case TokenType.Field:
339					return ret | 1;
340				case TokenType.TypeRef:
341					return ret | 2;
342				case TokenType.TypeDef:
343					return ret | 3;
344				case TokenType.Param:
345					return ret | 4;
346				case TokenType.InterfaceImpl:
347					return ret | 5;
348				case TokenType.MemberRef:
349					return ret | 6;
350				case TokenType.Module:
351					return ret | 7;
352				case TokenType.Permission:
353					return ret | 8;
354				case TokenType.Property:
355					return ret | 9;
356				case TokenType.Event:
357					return ret | 10;
358				case TokenType.Signature:
359					return ret | 11;
360				case TokenType.ModuleRef:
361					return ret | 12;
362				case TokenType.TypeSpec:
363					return ret | 13;
364				case TokenType.Assembly:
365					return ret | 14;
366				case TokenType.AssemblyRef:
367					return ret | 15;
368				case TokenType.File:
369					return ret | 16;
370				case TokenType.ExportedType:
371					return ret | 17;
372				case TokenType.ManifestResource:
373					return ret | 18;
374				case TokenType.GenericParam:
375					return ret | 19;
376				case TokenType.GenericParamConstraint:
377					return ret | 20;
378				case TokenType.MethodSpec:
379					return ret | 21;
380				default:
381					goto exit;
382				}
383			case CodedIndex.HasFieldMarshal:
384				ret = token.RID << 1;
385				switch (token.TokenType) {
386				case TokenType.Field:
387					return ret | 0;
388				case TokenType.Param:
389					return ret | 1;
390				default:
391					goto exit;
392				}
393			case CodedIndex.HasDeclSecurity:
394				ret = token.RID << 2;
395				switch (token.TokenType) {
396				case TokenType.TypeDef:
397					return ret | 0;
398				case TokenType.Method:
399					return ret | 1;
400				case TokenType.Assembly:
401					return ret | 2;
402				default:
403					goto exit;
404				}
405			case CodedIndex.MemberRefParent:
406				ret = token.RID << 3;
407				switch (token.TokenType) {
408				case TokenType.TypeDef:
409					return ret | 0;
410				case TokenType.TypeRef:
411					return ret | 1;
412				case TokenType.ModuleRef:
413					return ret | 2;
414				case TokenType.Method:
415					return ret | 3;
416				case TokenType.TypeSpec:
417					return ret | 4;
418				default:
419					goto exit;
420				}
421			case CodedIndex.HasSemantics:
422				ret = token.RID << 1;
423				switch (token.TokenType) {
424				case TokenType.Event:
425					return ret | 0;
426				case TokenType.Property:
427					return ret | 1;
428				default:
429					goto exit;
430				}
431			case CodedIndex.MethodDefOrRef:
432				ret = token.RID << 1;
433				switch (token.TokenType) {
434				case TokenType.Method:
435					return ret | 0;
436				case TokenType.MemberRef:
437					return ret | 1;
438				default:
439					goto exit;
440				}
441			case CodedIndex.MemberForwarded:
442				ret = token.RID << 1;
443				switch (token.TokenType) {
444				case TokenType.Field:
445					return ret | 0;
446				case TokenType.Method:
447					return ret | 1;
448				default:
449					goto exit;
450				}
451			case CodedIndex.Implementation:
452				ret = token.RID << 2;
453				switch (token.TokenType) {
454				case TokenType.File:
455					return ret | 0;
456				case TokenType.AssemblyRef:
457					return ret | 1;
458				case TokenType.ExportedType:
459					return ret | 2;
460				default:
461					goto exit;
462				}
463			case CodedIndex.CustomAttributeType:
464				ret = token.RID << 3;
465				switch (token.TokenType) {
466				case TokenType.Method:
467					return ret | 2;
468				case TokenType.MemberRef:
469					return ret | 3;
470				default:
471					goto exit;
472				}
473			case CodedIndex.ResolutionScope:
474				ret = token.RID << 2;
475				switch (token.TokenType) {
476				case TokenType.Module:
477					return ret | 0;
478				case TokenType.ModuleRef:
479					return ret | 1;
480				case TokenType.AssemblyRef:
481					return ret | 2;
482				case TokenType.TypeRef:
483					return ret | 3;
484				default:
485					goto exit;
486				}
487			case CodedIndex.TypeOrMethodDef:
488				ret = token.RID << 1;
489				switch (token.TokenType) {
490				case TokenType.TypeDef:
491					return ret | 0;
492				case TokenType.Method:
493					return ret | 1;
494				default:
495					goto exit;
496				}
497			case CodedIndex.HasCustomDebugInformation:
498				ret = token.RID << 5;
499				switch (token.TokenType) {
500				case TokenType.Method:
501					return ret | 0;
502				case TokenType.Field:
503					return ret | 1;
504				case TokenType.TypeRef:
505					return ret | 2;
506				case TokenType.TypeDef:
507					return ret | 3;
508				case TokenType.Param:
509					return ret | 4;
510				case TokenType.InterfaceImpl:
511					return ret | 5;
512				case TokenType.MemberRef:
513					return ret | 6;
514				case TokenType.Module:
515					return ret | 7;
516				case TokenType.Permission:
517					return ret | 8;
518				case TokenType.Property:
519					return ret | 9;
520				case TokenType.Event:
521					return ret | 10;
522				case TokenType.Signature:
523					return ret | 11;
524				case TokenType.ModuleRef:
525					return ret | 12;
526				case TokenType.TypeSpec:
527					return ret | 13;
528				case TokenType.Assembly:
529					return ret | 14;
530				case TokenType.AssemblyRef:
531					return ret | 15;
532				case TokenType.File:
533					return ret | 16;
534				case TokenType.ExportedType:
535					return ret | 17;
536				case TokenType.ManifestResource:
537					return ret | 18;
538				case TokenType.GenericParam:
539					return ret | 19;
540				case TokenType.GenericParamConstraint:
541					return ret | 20;
542				case TokenType.MethodSpec:
543					return ret | 21;
544				case TokenType.Document:
545					return ret | 22;
546				case TokenType.LocalScope:
547					return ret | 23;
548				case TokenType.LocalVariable:
549					return ret | 24;
550				case TokenType.LocalConstant:
551					return ret | 25;
552				case TokenType.ImportScope:
553					return ret | 26;
554				default:
555					goto exit;
556				}
557			default:
558				goto exit;
559			}
560		exit:
561			throw new ArgumentException ();
562		}
563
564		public static int GetSize (this CodedIndex self, Func<Table, int> counter)
565		{
566			int bits;
567			Table [] tables;
568
569			switch (self) {
570			case CodedIndex.TypeDefOrRef:
571				bits = 2;
572				tables = new [] { Table.TypeDef, Table.TypeRef, Table.TypeSpec };
573				break;
574			case CodedIndex.HasConstant:
575				bits = 2;
576				tables = new [] { Table.Field, Table.Param, Table.Property };
577				break;
578			case CodedIndex.HasCustomAttribute:
579				bits = 5;
580				tables = new [] {
581					Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
582					Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
583					Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
584					Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
585				};
586				break;
587			case CodedIndex.HasFieldMarshal:
588				bits = 1;
589				tables = new [] { Table.Field, Table.Param };
590				break;
591			case CodedIndex.HasDeclSecurity:
592				bits = 2;
593				tables = new [] { Table.TypeDef, Table.Method, Table.Assembly };
594				break;
595			case CodedIndex.MemberRefParent:
596				bits = 3;
597				tables = new [] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec };
598				break;
599			case CodedIndex.HasSemantics:
600				bits = 1;
601				tables = new [] { Table.Event, Table.Property };
602				break;
603			case CodedIndex.MethodDefOrRef:
604				bits = 1;
605				tables = new [] { Table.Method, Table.MemberRef };
606				break;
607			case CodedIndex.MemberForwarded:
608				bits = 1;
609				tables = new [] { Table.Field, Table.Method };
610				break;
611			case CodedIndex.Implementation:
612				bits = 2;
613				tables = new [] { Table.File, Table.AssemblyRef, Table.ExportedType };
614				break;
615			case CodedIndex.CustomAttributeType:
616				bits = 3;
617				tables = new [] { Table.Method, Table.MemberRef };
618				break;
619			case CodedIndex.ResolutionScope:
620				bits = 2;
621				tables = new [] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef };
622				break;
623			case CodedIndex.TypeOrMethodDef:
624				bits = 1;
625				tables = new [] { Table.TypeDef, Table.Method };
626				break;
627			case CodedIndex.HasCustomDebugInformation:
628				bits = 5;
629				tables = new[] {
630					Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
631					Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
632					Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
633					Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
634					Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope,
635				};
636				break;
637			default:
638				throw new ArgumentException ();
639			}
640
641			int max = 0;
642
643			for (int i = 0; i < tables.Length; i++) {
644				max = System.Math.Max (counter (tables [i]), max);
645			}
646
647			return max < (1 << (16 - bits)) ? 2 : 4;
648		}
649	}
650}