/Mono.Cecil.Metadata/Utilities.cs
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}