27
27
28
28
package org .jruby .ext .strscan ;
29
29
30
+ import jnr .a64asm .REG ;
30
31
import org .jcodings .Encoding ;
31
32
import org .joni .Matcher ;
32
33
import org .joni .NameEntry ;
@@ -102,6 +103,93 @@ public static RubyClass createScannerClass(final Ruby runtime) {
102
103
return scannerClass ;
103
104
}
104
105
106
+ // Provided temporarily to bridge the gap between joni 2.1 and 2.2
107
+ private static final RegionAdapter REGION_ADAPTER ;
108
+ static {
109
+ RegionAdapter adapter ;
110
+ try {
111
+ Region .class .getMethod ("newRegion" , int .class , int .class );
112
+ // ok, proceed with factory-based adapter
113
+ adapter = new FactoryRegionAdapter ();
114
+ } catch (NoSuchMethodException | SecurityException ex ) {
115
+ adapter = new OldRegionAdapter ();
116
+ }
117
+ REGION_ADAPTER = adapter ;
118
+ }
119
+
120
+ private interface RegionAdapter {
121
+ Region newRegion (int beg , int end );
122
+ int getBeg (Region region , int index );
123
+ int getEnd (Region region , int index );
124
+ int setBeg (Region region , int index , int value );
125
+ int setEnd (Region region , int index , int value );
126
+ int getNumRegs (Region region );
127
+ }
128
+
129
+ private static class OldRegionAdapter implements RegionAdapter {
130
+ @ Override
131
+ public Region newRegion (int beg , int end ) {
132
+ return new Region (beg , end );
133
+ }
134
+
135
+ @ Override
136
+ public int getBeg (Region region , int index ) {
137
+ return region .beg [index ];
138
+ }
139
+
140
+ @ Override
141
+ public int getEnd (Region region , int index ) {
142
+ return region .end [index ];
143
+ }
144
+
145
+ @ Override
146
+ public int setBeg (Region region , int index , int value ) {
147
+ return region .beg [index ] = value ;
148
+ }
149
+
150
+ @ Override
151
+ public int setEnd (Region region , int index , int value ) {
152
+ return region .end [index ] = value ;
153
+ }
154
+
155
+ @ Override
156
+ public int getNumRegs (Region region ) {
157
+ return region .numRegs ;
158
+ }
159
+ }
160
+
161
+ private static class FactoryRegionAdapter implements RegionAdapter {
162
+ @ Override
163
+ public Region newRegion (int beg , int end ) {
164
+ return Region .newRegion (beg , end );
165
+ }
166
+
167
+ @ Override
168
+ public int getBeg (Region region , int index ) {
169
+ return region .getBeg (index );
170
+ }
171
+
172
+ @ Override
173
+ public int getEnd (Region region , int index ) {
174
+ return region .getEnd (index );
175
+ }
176
+
177
+ @ Override
178
+ public int setBeg (Region region , int index , int value ) {
179
+ return region .setBeg (index , value );
180
+ }
181
+
182
+ @ Override
183
+ public int setEnd (Region region , int index , int value ) {
184
+ return region .setEnd (index , value );
185
+ }
186
+
187
+ @ Override
188
+ public int getNumRegs (Region region ) {
189
+ return region .getNumRegs ();
190
+ }
191
+ }
192
+
105
193
private void clearMatched () {
106
194
scannerFlags &= ~MATCHED_STR_SCN_F ;
107
195
}
@@ -131,7 +219,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject string) {
131
219
public IRubyObject initialize (ThreadContext context , IRubyObject string , IRubyObject dupOrOpts ) {
132
220
this .str = string .convertToString ();
133
221
this .fixedAnchor = ArgsUtil .extractKeywordArg (context , "fixed_anchor" , dupOrOpts ).isTrue ();
134
- this .regs = new Region (0 , 0 );
222
+ this .regs = REGION_ADAPTER . newRegion (0 , 0 );
135
223
136
224
return this ;
137
225
}
@@ -313,7 +401,7 @@ private IRubyObject scan(ThreadContext context, IRubyObject regex, boolean succp
313
401
314
402
Region matchRegion = matcher .getRegion ();
315
403
if (matchRegion == null ) {
316
- regs = new Region (matcher .getBegin (), matcher .getEnd ());
404
+ regs = REGION_ADAPTER . newRegion (matcher .getBegin (), matcher .getEnd ());
317
405
} else {
318
406
regs = matchRegion ;
319
407
}
@@ -359,17 +447,17 @@ private IRubyObject scan(ThreadContext context, IRubyObject regex, boolean succp
359
447
360
448
private int lastMatchLength () {
361
449
if (fixedAnchor ) {
362
- return regs . end [ 0 ] - prev ;
450
+ return REGION_ADAPTER . getEnd ( regs , 0 ) - prev ;
363
451
} else {
364
- return regs . end [ 0 ] ;
452
+ return REGION_ADAPTER . getEnd ( regs , 0 ) ;
365
453
}
366
454
}
367
455
368
456
private void succ () {
369
457
if (fixedAnchor ) {
370
- this .curr = this . regs . end [ 0 ] ;
458
+ this .curr = REGION_ADAPTER . getEnd ( regs , 0 ) ;
371
459
} else {
372
- this .curr += this . regs . end [ 0 ] ;
460
+ this .curr += REGION_ADAPTER . getEnd ( regs , 0 ) ;
373
461
}
374
462
}
375
463
@@ -392,9 +480,9 @@ private int restLen() {
392
480
// MRI: set_registers
393
481
private void setRegisters (int length ) {
394
482
if (fixedAnchor ) {
395
- regs = new Region (curr , curr + length );
483
+ regs = REGION_ADAPTER . newRegion (curr , curr + length );
396
484
} else {
397
- regs = new Region (0 , length );
485
+ regs = REGION_ADAPTER . newRegion (0 , length );
398
486
}
399
487
}
400
488
@@ -451,9 +539,9 @@ public IRubyObject search_full(ThreadContext context, IRubyObject regex, IRubyOb
451
539
// MRI: adjust_register_to_matched
452
540
private void adjustRegisters () {
453
541
if (fixedAnchor ) {
454
- regs = new Region (prev , curr );
542
+ regs = REGION_ADAPTER . newRegion (prev , curr );
455
543
} else {
456
- regs = new Region (0 , curr - prev );
544
+ regs = REGION_ADAPTER . newRegion (0 , curr - prev );
457
545
}
458
546
}
459
547
@@ -485,8 +573,8 @@ public IRubyObject getchCommon(ThreadContext context) {
485
573
adjustRegisters ();
486
574
487
575
return extractRange (runtime ,
488
- prev + regs . beg [ 0 ] ,
489
- prev + regs . end [ 0 ] );
576
+ prev + REGION_ADAPTER . getBeg ( regs , 0 ) ,
577
+ prev + REGION_ADAPTER . getEnd ( regs , 0 ) );
490
578
}
491
579
492
580
@ JRubyMethod (name = "get_byte" )
@@ -501,7 +589,7 @@ public IRubyObject get_byte(ThreadContext context) {
501
589
setMatched ();
502
590
adjustRegisters ();
503
591
504
- return extractRange (context .runtime , prev + regs . beg [ 0 ] , prev + regs . end [ 0 ] );
592
+ return extractRange (context .runtime , prev + REGION_ADAPTER . getBeg ( regs , 0 ) , prev + REGION_ADAPTER . getEnd ( regs , 0 ) );
505
593
}
506
594
507
595
@ JRubyMethod (name = "getbyte" )
@@ -596,14 +684,14 @@ public RubyBoolean matched_p(ThreadContext context) {
596
684
public IRubyObject matched (ThreadContext context ) {
597
685
check (context );
598
686
if (!isMatched ()) return context .nil ;
599
- return extractRange (context .runtime , prev + regs . beg [ 0 ] , prev + regs . end [ 0 ] );
687
+ return extractRange (context .runtime , prev + REGION_ADAPTER . getBeg ( regs , 0 ) , prev + REGION_ADAPTER . getEnd ( regs , 0 ) );
600
688
}
601
689
602
690
@ JRubyMethod (name = "matched_size" )
603
691
public IRubyObject matched_size (ThreadContext context ) {
604
692
check (context );
605
693
if (!isMatched ()) return context .nil ;
606
- return RubyFixnum .newFixnum (context .runtime , regs . end [ 0 ] - regs . beg [ 0 ] );
694
+ return RubyFixnum .newFixnum (context .runtime , REGION_ADAPTER . getEnd ( regs , 0 ) - REGION_ADAPTER . getBeg ( regs , 0 ) );
607
695
}
608
696
609
697
@ JRubyMethod (name = "matchedsize" )
@@ -635,14 +723,14 @@ public IRubyObject op_aref(ThreadContext context, IRubyObject idx) {
635
723
}
636
724
637
725
private IRubyObject extractRegion (ThreadContext context , int i ) {
638
- int numRegs = regs . numRegs ;
726
+ int numRegs = REGION_ADAPTER . getNumRegs ( regs ) ;
639
727
640
728
if (i < 0 ) i += numRegs ;
641
- if (i < 0 || i >= numRegs || regs . beg [ i ] == -1 ) {
729
+ if (i < 0 || i >= numRegs || REGION_ADAPTER . getBeg ( regs , i ) == -1 ) {
642
730
return context .nil ;
643
731
}
644
732
645
- return extractRange (context .runtime , prev + regs . beg [ i ] , prev + regs . end [ i ] );
733
+ return extractRange (context .runtime , prev + REGION_ADAPTER . getBeg ( regs , i ) , prev + REGION_ADAPTER . getEnd ( regs , i ) );
646
734
}
647
735
648
736
@ JRubyMethod (name = "pre_match" )
@@ -651,7 +739,7 @@ public IRubyObject pre_match(ThreadContext context) {
651
739
if (!isMatched ()) {
652
740
return context .nil ;
653
741
}
654
- return extractRange (context .runtime , 0 , prev + regs . beg [ 0 ] );
742
+ return extractRange (context .runtime , 0 , prev + REGION_ADAPTER . getBeg ( regs , 0 ) );
655
743
}
656
744
657
745
@ JRubyMethod (name = "post_match" )
@@ -662,7 +750,7 @@ public IRubyObject post_match(ThreadContext context) {
662
750
return context .nil ;
663
751
}
664
752
665
- return extractRange (context .runtime , prev + regs . end [ 0 ] , str .getByteList ().getRealSize ());
753
+ return extractRange (context .runtime , prev + REGION_ADAPTER . getEnd ( regs , 0 ) , str .getByteList ().getRealSize ());
666
754
}
667
755
668
756
@ JRubyMethod (name = "rest" )
@@ -769,7 +857,7 @@ private IRubyObject inspect2() {
769
857
@ JRubyMethod (name = "size" )
770
858
public IRubyObject size (ThreadContext context ) {
771
859
if (!isMatched ()) return context .nil ;
772
- return context .runtime .newFixnum (regs . numRegs );
860
+ return context .runtime .newFixnum (REGION_ADAPTER . getNumRegs ( regs ) );
773
861
}
774
862
775
863
@ JRubyMethod (name = "captures" )
@@ -781,11 +869,11 @@ public IRubyObject captures(ThreadContext context) {
781
869
782
870
Ruby runtime = context .runtime ;
783
871
784
- numRegs = regs . numRegs ;
872
+ numRegs = REGION_ADAPTER . getNumRegs ( regs ) ;
785
873
newAry = RubyArray .newArray (runtime , numRegs );
786
874
787
875
for (i = 1 ; i < numRegs ; i ++) {
788
- IRubyObject str = extractRange (runtime , prev + regs . beg [ i ] , prev + regs . end [ i ] );
876
+ IRubyObject str = extractRange (runtime , prev + REGION_ADAPTER . getBeg ( regs , i ) , prev + REGION_ADAPTER . getEnd ( regs , i ) );
789
877
newAry .push (str );
790
878
}
791
879
0 commit comments