зеркало из https://github.com/github/ruby.git
[ruby/prism] Shared integer parsing logic
https://github.com/ruby/prism/commit/a2594a23c1
This commit is contained in:
Родитель
c1462250b8
Коммит
f5294ebbdb
|
@ -1047,30 +1047,16 @@ integer_parse(VALUE self, VALUE source) {
|
||||||
pm_integer_t integer = { 0 };
|
pm_integer_t integer = { 0 };
|
||||||
pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length);
|
pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length);
|
||||||
|
|
||||||
VALUE number;
|
|
||||||
|
|
||||||
if (integer.values == NULL) {
|
|
||||||
number = UINT2NUM(integer.value);
|
|
||||||
} else {
|
|
||||||
number = UINT2NUM(0);
|
|
||||||
for (size_t i = 0; i < integer.length; i++) {
|
|
||||||
VALUE receiver = rb_funcall(UINT2NUM(integer.values[i]), rb_intern("<<"), 1, ULONG2NUM(i * 32));
|
|
||||||
number = rb_funcall(receiver, rb_intern("|"), 1, number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (integer.negative) number = rb_funcall(number, rb_intern("-@"), 0);
|
|
||||||
|
|
||||||
pm_buffer_t buffer = { 0 };
|
pm_buffer_t buffer = { 0 };
|
||||||
pm_integer_string(&buffer, &integer);
|
pm_integer_string(&buffer, &integer);
|
||||||
|
|
||||||
VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer));
|
VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer));
|
||||||
pm_buffer_free(&buffer);
|
pm_buffer_free(&buffer);
|
||||||
pm_integer_free(&integer);
|
|
||||||
|
|
||||||
VALUE result = rb_ary_new_capa(2);
|
VALUE result = rb_ary_new_capa(2);
|
||||||
rb_ary_push(result, number);
|
rb_ary_push(result, pm_integer_new(&integer));
|
||||||
rb_ary_push(result, string);
|
rb_ary_push(result, string);
|
||||||
|
pm_integer_free(&integer);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding);
|
VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding);
|
||||||
VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source);
|
VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source);
|
||||||
VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source);
|
VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source);
|
||||||
|
VALUE pm_integer_new(const pm_integer_t *integer);
|
||||||
|
|
||||||
void Init_prism_api_node(void);
|
void Init_prism_api_node(void);
|
||||||
void Init_prism_pack(void);
|
void Init_prism_pack(void);
|
||||||
|
|
|
@ -37,23 +37,26 @@ pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
|
||||||
return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding);
|
return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
VALUE
|
||||||
pm_integer_new(const pm_integer_t *integer) {
|
pm_integer_new(const pm_integer_t *integer) {
|
||||||
VALUE result;
|
VALUE result;
|
||||||
if (integer->values) {
|
if (integer->values == NULL) {
|
||||||
VALUE str = rb_str_new(NULL, integer->length * 8);
|
|
||||||
unsigned char *buf = (unsigned char *)RSTRING_PTR(str);
|
|
||||||
size_t offset = integer->length * 8;
|
|
||||||
for (size_t i = 0; i < integer->length; i++) {
|
|
||||||
uint32_t value = integer->values[i];
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
int n = (value >> (4 * i)) & 0xf;
|
|
||||||
buf[--offset] = n < 10 ? n + '0' : n - 10 + 'a';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = rb_funcall(str, rb_intern("to_i"), 1, UINT2NUM(16));
|
|
||||||
} else {
|
|
||||||
result = UINT2NUM(integer->value);
|
result = UINT2NUM(integer->value);
|
||||||
|
} else {
|
||||||
|
VALUE string = rb_str_new(NULL, integer->length * 8);
|
||||||
|
unsigned char *bytes = (unsigned char *) RSTRING_PTR(string);
|
||||||
|
|
||||||
|
size_t offset = integer->length * 8;
|
||||||
|
for (size_t value_index = 0; value_index < integer->length; value_index++) {
|
||||||
|
uint32_t value = integer->values[value_index];
|
||||||
|
|
||||||
|
for (int index = 0; index < 8; index++) {
|
||||||
|
int byte = (value >> (4 * index)) & 0xf;
|
||||||
|
bytes[--offset] = byte < 10 ? byte + '0' : byte - 10 + 'a';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = rb_funcall(string, rb_intern("to_i"), 1, UINT2NUM(16));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (integer->negative) {
|
if (integer->negative) {
|
||||||
|
|
|
@ -29,8 +29,9 @@ big_add(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint
|
||||||
|
|
||||||
size_t length = left_length < right_length ? right_length : left_length;
|
size_t length = left_length < right_length ? right_length : left_length;
|
||||||
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * (length + 1));
|
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * (length + 1));
|
||||||
uint64_t carry = 0;
|
if (values == NULL) return;
|
||||||
|
|
||||||
|
uint64_t carry = 0;
|
||||||
for (size_t index = 0; index < length; index++) {
|
for (size_t index = 0; index < length; index++) {
|
||||||
uint64_t sum = carry + (index < left_length ? left_values[index] : 0) + (index < right_length ? right_values[index] : 0);
|
uint64_t sum = carry + (index < left_length ? left_values[index] : 0) + (index < right_length ? right_values[index] : 0);
|
||||||
values[index] = (uint32_t) (sum % base);
|
values[index] = (uint32_t) (sum % base);
|
||||||
|
@ -54,36 +55,15 @@ static void
|
||||||
big_sub2(pm_integer_t *destination, pm_integer_t *a, pm_integer_t *b, pm_integer_t *c, uint64_t base) {
|
big_sub2(pm_integer_t *destination, pm_integer_t *a, pm_integer_t *b, pm_integer_t *c, uint64_t base) {
|
||||||
size_t a_length;
|
size_t a_length;
|
||||||
uint32_t *a_values;
|
uint32_t *a_values;
|
||||||
|
INTEGER_EXTRACT(a, a_length, a_values)
|
||||||
if (a->values == NULL) {
|
|
||||||
a_length = 1;
|
|
||||||
a_values = &a->value;
|
|
||||||
} else {
|
|
||||||
a_length = a->length;
|
|
||||||
a_values = a->values;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t b_length;
|
size_t b_length;
|
||||||
uint32_t *b_values;
|
uint32_t *b_values;
|
||||||
|
INTEGER_EXTRACT(b, b_length, b_values)
|
||||||
if (b->values == NULL) {
|
|
||||||
b_length = 1;
|
|
||||||
b_values = &b->value;
|
|
||||||
} else {
|
|
||||||
b_length = b->length;
|
|
||||||
b_values = b->values;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t c_length;
|
size_t c_length;
|
||||||
uint32_t *c_values;
|
uint32_t *c_values;
|
||||||
|
INTEGER_EXTRACT(c, c_length, c_values)
|
||||||
if (c->values == NULL) {
|
|
||||||
c_length = 1;
|
|
||||||
c_values = &c->value;
|
|
||||||
} else {
|
|
||||||
c_length = c->length;
|
|
||||||
c_values = c->values;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t *values = (uint32_t*) xmalloc(sizeof(uint32_t) * a_length);
|
uint32_t *values = (uint32_t*) xmalloc(sizeof(uint32_t) * a_length);
|
||||||
int64_t carry = 0;
|
int64_t carry = 0;
|
||||||
|
@ -137,6 +117,7 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *
|
||||||
if (left_length <= 10) {
|
if (left_length <= 10) {
|
||||||
size_t length = left_length + right_length;
|
size_t length = left_length + right_length;
|
||||||
uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t));
|
uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t));
|
||||||
|
if (values == NULL) return;
|
||||||
|
|
||||||
for (size_t left_index = 0; left_index < left_length; left_index++) {
|
for (size_t left_index = 0; left_index < left_length; left_index++) {
|
||||||
uint32_t carry = 0;
|
uint32_t carry = 0;
|
||||||
|
@ -293,6 +274,8 @@ pm_integer_from_uint64(pm_integer_t *integer, uint64_t value, uint64_t base) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * length);
|
uint32_t *values = (uint32_t *) xmalloc(sizeof(uint32_t) * length);
|
||||||
|
if (values == NULL) return;
|
||||||
|
|
||||||
for (size_t value_index = 0; value_index < length; value_index++) {
|
for (size_t value_index = 0; value_index < length; value_index++) {
|
||||||
values[value_index] = (uint32_t) (value % base);
|
values[value_index] = (uint32_t) (value % base);
|
||||||
value /= base;
|
value /= base;
|
||||||
|
@ -340,6 +323,7 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u
|
||||||
|
|
||||||
size_t bigints_length = (source_length + 1) / 2;
|
size_t bigints_length = (source_length + 1) / 2;
|
||||||
pm_integer_t *bigints = (pm_integer_t *) xcalloc(bigints_length, sizeof(pm_integer_t));
|
pm_integer_t *bigints = (pm_integer_t *) xcalloc(bigints_length, sizeof(pm_integer_t));
|
||||||
|
if (bigints == NULL) return;
|
||||||
|
|
||||||
for (size_t index = 0; index < source_length; index += 2) {
|
for (size_t index = 0; index < source_length; index += 2) {
|
||||||
uint64_t value = source_values[index] + base_from * (index + 1 < source_length ? source_values[index + 1] : 0);
|
uint64_t value = source_values[index] + base_from * (index + 1 < source_length ? source_values[index + 1] : 0);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче