@@ -115,8 +115,7 @@ public final BigInteger getValue() {
115
115
}
116
116
117
117
@ JRubyMethod (name ="initialize" , required =1 , optional =1 , visibility = Visibility .PRIVATE )
118
- public IRubyObject initialize (final ThreadContext context ,
119
- final IRubyObject [] args ) {
118
+ public IRubyObject initialize (final ThreadContext context , final IRubyObject [] args ) {
120
119
final Ruby runtime = context .runtime ;
121
120
if (this .value != BigInteger .ZERO ) { // already initialized
122
121
throw newBNError (runtime , "illegal initialization" );
@@ -126,14 +125,7 @@ public IRubyObject initialize(final ThreadContext context,
126
125
final RubyString str = args [0 ].asString ();
127
126
switch (base ) {
128
127
case 0 :
129
- final byte [] bytes = str .getBytes (); final int signum ;
130
- if ( ( bytes [0 ] & 0x80 ) != 0 ) {
131
- bytes [0 ] &= 0x7f ; signum = -1 ;
132
- }
133
- else {
134
- signum = 1 ;
135
- }
136
- this .value = new BigInteger (signum , bytes );
128
+ this .value = initBigIntegerMPI (runtime , str );
137
129
break ;
138
130
case 2 :
139
131
// this seems wrong to me, but is the behavior of the
@@ -147,18 +139,44 @@ public IRubyObject initialize(final ThreadContext context,
147
139
case 10 :
148
140
case 16 :
149
141
// here, the ASCII-encoded decimal or hex string is used
150
- try {
151
- this .value = new BigInteger (str .toString (), base );
152
- break ;
153
- } catch (NumberFormatException e ) {
154
- throw runtime .newArgumentError ("value " + str + " is not legal for radix " + base );
155
- }
142
+ this .value = initBigIntegerBase (runtime , str , base );
143
+ break ;
156
144
default :
157
145
throw runtime .newArgumentError ("illegal radix: " + base );
158
146
}
159
147
return this ;
160
148
}
161
149
150
+ private static BigInteger initBigIntegerMPI (final Ruby runtime , RubyString str ) {
151
+ final ByteList byteList = str .getByteList ();
152
+ final int off = byteList .getBegin ();
153
+ final byte [] b = byteList .getUnsafeBytes ();
154
+
155
+ long len = ((b [off ] & 0xFFl ) << 24 ) | ((b [off +1 ] & 0xFF ) << 16 ) | ((b [off +2 ] & 0xFF ) << 8 ) | (b [off +3 ] & 0xFF );
156
+ final byte [] bytes = new byte [(int ) len ];
157
+ System .arraycopy (b , off + 4 , bytes , 0 , bytes .length );
158
+
159
+ final int signum ;
160
+ if ( (bytes [0 ] & 0x80 ) == 0x80 ) {
161
+ signum = -1 ; bytes [0 ] &= 0x7f ;
162
+ }
163
+ else {
164
+ signum = +1 ;
165
+ }
166
+ return new BigInteger (signum , bytes );
167
+
168
+ }
169
+
170
+ private static BigInteger initBigIntegerBase (final Ruby runtime , RubyString str , final int base ) {
171
+ // here, the ASCII-encoded decimal or hex string is used
172
+ try {
173
+ return new BigInteger (str .toString (), base );
174
+ }
175
+ catch (NumberFormatException e ) {
176
+ throw runtime .newArgumentError ("value " + str + " is not legal for radix " + base );
177
+ }
178
+ }
179
+
162
180
@ Override
163
181
public IRubyObject initialize_copy (final IRubyObject that ) {
164
182
super .initialize_copy (that );
0 commit comments