@@ -34,6 +34,12 @@ private void SetOutOfBounds(int direction)
34
34
Pos = direction > 0 ? Length : - 1 ;
35
35
}
36
36
37
+ private int PosOrThrow ( )
38
+ {
39
+ if ( IsInvalid ) throw new InvalidOperationException ( "Current position is out of bounds" ) ;
40
+ return Pos ;
41
+ }
42
+
37
43
/// <summary>Gets the number of code instructions in this matcher</summary>
38
44
/// <value>The count</value>
39
45
///
@@ -52,27 +58,27 @@ private void SetOutOfBounds(int direction)
52
58
/// <summary>Gets the remaining code instructions</summary>
53
59
/// <value>The remaining count</value>
54
60
///
55
- public int Remaining => Length - Math . Max ( 0 , Pos ) ;
61
+ public int Remaining => Length - PosOrThrow ( ) ;
56
62
57
63
/// <summary>Gets the opcode at the current position</summary>
58
64
/// <value>The opcode</value>
59
65
///
60
- public ref OpCode Opcode => ref codes [ Pos ] . opcode ;
66
+ public ref OpCode Opcode => ref codes [ PosOrThrow ( ) ] . opcode ;
61
67
62
68
/// <summary>Gets the operand at the current position</summary>
63
69
/// <value>The operand</value>
64
70
///
65
- public ref object Operand => ref codes [ Pos ] . operand ;
71
+ public ref object Operand => ref codes [ PosOrThrow ( ) ] . operand ;
66
72
67
73
/// <summary>Gets the labels at the current position</summary>
68
74
/// <value>The labels</value>
69
75
///
70
- public ref List < Label > Labels => ref codes [ Pos ] . labels ;
76
+ public ref List < Label > Labels => ref codes [ PosOrThrow ( ) ] . labels ;
71
77
72
78
/// <summary>Gets the exception blocks at the current position</summary>
73
79
/// <value>The blocks</value>
74
80
///
75
- public ref List < ExceptionBlock > Blocks => ref codes [ Pos ] . blocks ;
81
+ public ref List < ExceptionBlock > Blocks => ref codes [ PosOrThrow ( ) ] . blocks ;
76
82
77
83
/// <summary>Creates an empty code matcher</summary>
78
84
public CodeMatcher ( )
@@ -85,6 +91,7 @@ public CodeMatcher()
85
91
///
86
92
public CodeMatcher ( IEnumerable < CodeInstruction > instructions , ILGenerator generator = null )
87
93
{
94
+ if ( instructions == null ) throw new ArgumentNullException ( nameof ( instructions ) ) ;
88
95
this . generator = generator ;
89
96
codes = instructions . Select ( c => new CodeInstruction ( c ) ) . ToList ( ) ;
90
97
}
@@ -103,15 +110,18 @@ public CodeMatcher Clone()
103
110
/// <summary>Gets instructions at the current position</summary>
104
111
/// <value>The instruction</value>
105
112
///
106
- public CodeInstruction Instruction => codes [ Pos ] ;
113
+ public CodeInstruction Instruction => codes [ PosOrThrow ( ) ] ;
107
114
108
115
/// <summary>Gets instructions at the current position with offset</summary>
109
116
/// <param name="offset">The offset</param>
110
117
/// <returns>The instruction</returns>
111
118
///
112
119
public CodeInstruction InstructionAt ( int offset )
113
120
{
114
- return codes [ Pos + offset ] ;
121
+ var pos = PosOrThrow ( ) ;
122
+ var newPos = pos + offset ;
123
+ if ( newPos < 0 || newPos >= Length ) throw new ArgumentOutOfRangeException ( nameof ( offset ) , "offset causes position to go out of bounds" ) ;
124
+ return codes [ newPos ] ;
115
125
}
116
126
117
127
/// <summary>Gets all instructions</summary>
@@ -136,7 +146,7 @@ public IEnumerable<CodeInstruction> InstructionEnumeration()
136
146
///
137
147
public List < CodeInstruction > Instructions ( int count )
138
148
{
139
- return codes . GetRange ( Pos , count ) . Select ( c => new CodeInstruction ( c ) ) . ToList ( ) ;
149
+ return codes . GetRange ( PosOrThrow ( ) , count ) . Select ( c => new CodeInstruction ( c ) ) . ToList ( ) ;
140
150
}
141
151
142
152
/// <summary>Gets all instructions within a range</summary>
@@ -163,7 +173,12 @@ public List<CodeInstruction> InstructionsInRange(int start, int end)
163
173
///
164
174
public List < CodeInstruction > InstructionsWithOffsets ( int startOffset , int endOffset )
165
175
{
166
- return InstructionsInRange ( Pos + startOffset , Pos + endOffset ) ;
176
+ var pos = PosOrThrow ( ) ;
177
+ var startPos = pos + startOffset ;
178
+ if ( startPos < 0 || startPos >= Length ) throw new ArgumentOutOfRangeException ( nameof ( startOffset ) , "startOffset causes position to go out of bounds" ) ;
179
+ var endPos = pos + endOffset ;
180
+ if ( endPos < 0 || endPos >= Length ) throw new ArgumentOutOfRangeException ( nameof ( endOffset ) , "endOffset causes position to go out of bounds" ) ;
181
+ return InstructionsInRange ( startPos , endPos ) ;
167
182
}
168
183
169
184
/// <summary>Gets a list of all distinct labels</summary>
@@ -276,7 +291,7 @@ public CodeMatcher ThrowIfFalse(string explanation, Func<CodeMatcher, bool> stat
276
291
///
277
292
public CodeMatcher SetInstruction ( CodeInstruction instruction )
278
293
{
279
- codes [ Pos ] = instruction ;
294
+ codes [ PosOrThrow ( ) ] = instruction ;
280
295
return this ;
281
296
}
282
297
@@ -388,6 +403,7 @@ public CodeMatcher AddLabels(IEnumerable<Label> labels)
388
403
///
389
404
public CodeMatcher AddLabelsAt ( int position , IEnumerable < Label > labels )
390
405
{
406
+ if ( position < 0 || position >= Length ) throw new ArgumentOutOfRangeException ( nameof ( position ) , "position is out of bounds" ) ;
391
407
codes [ position ] . labels . AddRange ( labels ) ;
392
408
return this ;
393
409
}
@@ -410,7 +426,10 @@ public CodeMatcher SetJumpTo(OpCode opcode, int destination, out Label label)
410
426
///
411
427
public CodeMatcher Insert ( params CodeInstruction [ ] instructions )
412
428
{
413
- codes . InsertRange ( Pos , instructions ) ;
429
+ if ( Pos == Length )
430
+ codes . AddRange ( instructions ) ;
431
+ else
432
+ codes . InsertRange ( PosOrThrow ( ) , instructions ) ;
414
433
return this ;
415
434
}
416
435
@@ -420,7 +439,10 @@ public CodeMatcher Insert(params CodeInstruction[] instructions)
420
439
///
421
440
public CodeMatcher Insert ( IEnumerable < CodeInstruction > instructions )
422
441
{
423
- codes . InsertRange ( Pos , instructions ) ;
442
+ if ( Pos == Length )
443
+ codes . AddRange ( instructions ) ;
444
+ else
445
+ codes . InsertRange ( PosOrThrow ( ) , instructions ) ;
424
446
return this ;
425
447
}
426
448
@@ -431,8 +453,9 @@ public CodeMatcher Insert(IEnumerable<CodeInstruction> instructions)
431
453
///
432
454
public CodeMatcher InsertBranch ( OpCode opcode , int destination )
433
455
{
456
+ var pos = PosOrThrow ( ) ;
434
457
_ = CreateLabelAt ( destination , out var label ) ;
435
- codes . Insert ( Pos , new CodeInstruction ( opcode , label ) ) ;
458
+ codes . Insert ( pos , new CodeInstruction ( opcode , label ) ) ;
436
459
return this ;
437
460
}
438
461
@@ -479,7 +502,7 @@ public CodeMatcher InsertBranchAndAdvance(OpCode opcode, int destination)
479
502
///
480
503
public CodeMatcher RemoveInstruction ( )
481
504
{
482
- codes . RemoveAt ( Pos ) ;
505
+ codes . RemoveAt ( PosOrThrow ( ) ) ;
483
506
return this ;
484
507
}
485
508
@@ -489,7 +512,7 @@ public CodeMatcher RemoveInstruction()
489
512
///
490
513
public CodeMatcher RemoveInstructions ( int count )
491
514
{
492
- codes . RemoveRange ( Pos , count ) ;
515
+ codes . RemoveRange ( PosOrThrow ( ) , count ) ;
493
516
return this ;
494
517
}
495
518
@@ -500,6 +523,9 @@ public CodeMatcher RemoveInstructions(int count)
500
523
///
501
524
public CodeMatcher RemoveInstructionsInRange ( int start , int end )
502
525
{
526
+ if ( start < 0 || start >= Length ) throw new ArgumentOutOfRangeException ( nameof ( start ) , "start is out of bounds" ) ;
527
+ if ( end < 0 || end >= Length ) throw new ArgumentOutOfRangeException ( nameof ( end ) , "end is out of bounds" ) ;
528
+
503
529
if ( start > end )
504
530
{
505
531
( start , end ) = ( end , start ) ;
@@ -578,7 +604,7 @@ public CodeMatcher SearchBackwards(Func<CodeInstruction, bool> predicate)
578
604
579
605
private CodeMatcher Search ( Func < CodeInstruction , bool > predicate , int direction )
580
606
{
581
- FixStart ( ) ;
607
+ FixStart ( ) ; //todo: Should invalid position throw instead? Breaking change
582
608
while ( IsValid && predicate ( Instruction ) == false )
583
609
Pos += direction ;
584
610
lastError = IsInvalid ? $ "Cannot find { predicate } " : null ;
@@ -642,9 +668,9 @@ public CodeMatcher MatchEndBackwards(params CodeMatch[] matches)
642
668
643
669
private CodeMatcher Match ( CodeMatch [ ] matches , int direction , bool useEnd )
644
670
{
645
- lastMatchCall = delegate ( )
671
+ lastMatchCall = delegate ( )
646
672
{
647
- FixStart ( ) ;
673
+ FixStart ( ) ; //todo: Should invalid position throw instead? Breaking change
648
674
while ( IsValid )
649
675
{
650
676
if ( MatchSequence ( Pos , matches ) )
0 commit comments