@@ -219,3 +219,99 @@ inline op nqp_bigint_bnot(out PMC, in PMC) :base_cor {
219
219
mp_add_d(a, 1, b);
220
220
mp_neg(b, b);
221
221
}
222
+
223
+
224
+ /*
225
+
226
+ =item nqp_bigint_radix(out, radix, str, pos, flag, type)
227
+
228
+ Convert string $3 into a number starting at offset $4 and using radix $2.
229
+ The result of the conversion returns an object of type $6, which is either
230
+ a bigint or some type that boxes one.
231
+
232
+ The $5 flags is a bitmask that modifies the parse and/or result:
233
+ 0x01: negate the result (useful if you've already parsed a minus)
234
+ 0x02: parse a leading +/- and negate the result on -
235
+ 0x04: parse trailing zeroes but do not include in result
236
+ (for parsing values after a decimal point)
237
+
238
+ =cut
239
+
240
+ */
241
+
242
+ inline op nqp_radix(out PMC, in INT, in STR, in INT, in INT, in PMC) :base_core {
243
+ PMC *out;
244
+ INTVAL radix = $2;
245
+ STRING *str = $3;
246
+ INTVAL zpos = $4;
247
+ INTVAL flags = $5;
248
+ INTVAL chars = Parrot_str_length(interp, str);
249
+ int neg = 0;
250
+ INTVAL ch;
251
+ mp_int zvalue;
252
+ mp_int zbase;
253
+ PMC *value_obj;
254
+ mp_int *value;
255
+ PMC *base_obj;
256
+ mp_int *base;
257
+ PMC *pos_obj;
258
+ INTVAL pos = -1;
259
+
260
+ if (radix > 36) {
261
+ Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
262
+ "Cannot convert radix of %d (max 36)", radix);
263
+ }
264
+
265
+ mp_init(&zvalue);
266
+ mp_init(&zbase);
267
+ mp_set_int(&zbase, 1);
268
+
269
+ value_obj = REPR($6)->allocate(interp, STABLE($6));
270
+ REPR(value_obj)->initialize(interp, STABLE(value_obj), OBJECT_BODY(value_obj));
271
+ value = get_bigint(interp, value_obj);
272
+
273
+ base_obj = REPR($6)->allocate(interp, STABLE($6));
274
+ REPR(base_obj)->initialize(interp, STABLE(base_obj), OBJECT_BODY(base_obj));
275
+ base = get_bigint(interp, base_obj);
276
+ mp_set_int(base, 1);
277
+
278
+ ch = (zpos < chars) ? STRING_ord(interp, str, zpos) : 0;
279
+ if ((flags & 0x02) && (ch == '+' || ch == '-')) {
280
+ neg = (ch == '-');
281
+ zpos++;
282
+ ch = (zpos < chars) ? STRING_ord(interp, str, zpos) : 0;
283
+ }
284
+ while (zpos < chars) {
285
+ if (ch >= '0' && ch <= '9') ch = ch - '0';
286
+ else if (ch >= 'a' && ch <= 'z') ch = ch - 'a' + 10;
287
+ else if (ch >= 'A' && ch <= 'Z') ch = ch - 'A' + 10;
288
+ else break;
289
+ if (ch >= radix) break;
290
+ mp_mul_d(&zvalue, radix, &zvalue);
291
+ mp_add_d(&zvalue, ch, &zvalue);
292
+ mp_mul_d(&zbase, radix, &zbase);
293
+ zpos++; pos = zpos;
294
+ if (ch != 0 || !(flags & 0x04)) { mp_copy(&zvalue, value); mp_copy(&zbase, base); }
295
+ if (zpos >= chars) break;
296
+ ch = STRING_ord(interp, str, zpos);
297
+ if (ch != '_') continue;
298
+ zpos++;
299
+ if (zpos >= chars) break;
300
+ ch = STRING_ord(interp, str, zpos);
301
+ }
302
+
303
+ mp_clear(&zvalue);
304
+ mp_clear(&zbase);
305
+
306
+ pos_obj = REPR($6)->allocate(interp, STABLE($6));
307
+ REPR(pos_obj)->initialize(interp, STABLE(pos_obj), OBJECT_BODY(pos_obj));
308
+ REPR(pos_obj)->set_int(interp, STABLE(pos_obj), OBJECT_BODY(pos_obj), pos);
309
+
310
+ if (neg || flags & 0x01) { mp_neg(value, value); }
311
+ out = pmc_new(interp, enum_class_FixedPMCArray);
312
+ VTABLE_set_integer_native(interp, out, 3);
313
+ VTABLE_set_pmc_keyed_int(interp, out, 0, value_obj);
314
+ VTABLE_set_pmc_keyed_int(interp, out, 1, base_obj);
315
+ VTABLE_set_pmc_keyed_int(interp, out, 2, pos_obj);
316
+ $1 = out;
317
+ }
0 commit comments