Skip to content

Commit

Permalink
Split ruby.c in multiple files, about one file per Ruby class
Browse files Browse the repository at this point in the history
  • Loading branch information
eregon committed May 5, 2020
1 parent 19f457a commit d83ddc3
Show file tree
Hide file tree
Showing 41 changed files with 3,508 additions and 3,432 deletions.
1 change: 1 addition & 0 deletions lib/cext/include/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define STR_SHARED_P(str) (str, false)

VALUE rb_hash_key_str(VALUE);
VALUE rb_hash_keys(VALUE hash);
VALUE rb_hash_delete_entry(VALUE hash, VALUE key);

VALUE rb_int_positive_pow(long x, unsigned long y);
Expand Down
13 changes: 13 additions & 0 deletions src/main/c/cext/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
All *.c and *.h files in this directory are licensed under:

Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved. This
code is released under a tri EPL/GPL/LGPL license. You can use it,
redistribute it and/or modify it under the terms of the:

Eclipse Public License version 2.0, or
GNU General Public License version 2, or
GNU Lesser General Public License version 2.1.

These files contain code that is based on the Ruby API headers and implementation,
copyright (C) Yukihiro Matsumoto, licensed under the 2-clause BSD licence
as described in the file BSDL included with TruffleRuby.
72 changes: 72 additions & 0 deletions src/main/c/cext/alloc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <truffleruby-impl.h>

// Memory-related function, *alloc*, *free*, rb_mem*

void ruby_malloc_size_overflow(size_t count, size_t elsize) {
rb_raise(rb_eArgError,
"malloc: possible integer overflow (%"PRIdSIZE"*%"PRIdSIZE")",
count, elsize);
}

size_t xmalloc2_size(const size_t count, const size_t elsize) {
size_t ret;
if (rb_mul_size_overflow(count, elsize, SSIZE_MAX, &ret)) {
ruby_malloc_size_overflow(count, elsize);
}
return ret;
}

void *ruby_xmalloc(size_t size) {
return malloc(size);
}

void *ruby_xmalloc2(size_t n, size_t size) {
size_t total_size = xmalloc2_size(n, size);
if (total_size == 0) {
total_size = 1;
}
return malloc(xmalloc2_size(n, total_size));
}

void *ruby_xcalloc(size_t n, size_t size) {
return calloc(n, size);
}

void *ruby_xrealloc(void *ptr, size_t new_size) {
return realloc(ptr, new_size);
}

void *ruby_xrealloc2(void *ptr, size_t n, size_t size) {
size_t len = size * n;
if (n != 0 && size != len / n) {
rb_raise(rb_eArgError, "realloc: possible integer overflow");
}
return realloc(ptr, len);
}

void ruby_xfree(void *address) {
free(address);
}

void *rb_alloc_tmp_buffer(volatile VALUE *store, long len) {
if (len == 0) {
len = 1;
}
void *ptr = malloc(len);
*((void**)store) = ptr;
return ptr;
}

void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt) {
return rb_alloc_tmp_buffer(store, size);
}

void rb_free_tmp_buffer(volatile VALUE *store) {
free(*((void**)store));
}

void rb_mem_clear(VALUE *mem, long n) {
for (int i = 0; i < n; i++) {
mem[i] = Qnil;
}
}
93 changes: 93 additions & 0 deletions src/main/c/cext/args.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <truffleruby-impl.h>
#include <internal.h>

// Parsing Ruby arguments from C functions

static VALUE rb_keyword_error_new(const char *error, VALUE keys) {
long i = 0, len = RARRAY_LEN(keys);
VALUE error_message = rb_sprintf("%s keyword%.*s", error, len > 1, "s");

if (len > 0) {
rb_str_append(error_message, rb_str_new_cstr(": "));
while (1) {
const VALUE k = RARRAY_AREF(keys, i);
Check_Type(k, T_SYMBOL); /* wrong hash is given to rb_get_kwargs */
rb_str_append(error_message, rb_sym2str(k));
if (++i >= len) break;
rb_str_append(error_message, rb_str_new_cstr(", "));
}
}

return rb_exc_new_str(rb_eArgError, error_message);
}

NORETURN(static void rb_keyword_error(const char *error, VALUE keys)) {
rb_exc_raise(rb_keyword_error_new(error, keys));
}

NORETURN(static void unknown_keyword_error(VALUE hash, const ID *table, int keywords)) {
int i;
for (i = 0; i < keywords; i++) {
VALUE key = table[i];
rb_hash_delete(hash, key);
}
rb_keyword_error("unknown", rb_hash_keys(hash));
}

static VALUE rb_tr_extract_keyword(VALUE keyword_hash, ID key, VALUE *values) {
VALUE val = rb_hash_lookup2(keyword_hash, key, Qundef);
if (values) {
rb_hash_delete(keyword_hash, key);
}
return val;
}

int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values) {
int rest = 0;
int extracted = 0;
VALUE missing = Qnil;

if (optional < 0) {
rest = 1;
optional = -1-optional;
}

for (int n = 0; n < required; n++) {
VALUE val = rb_tr_extract_keyword(keyword_hash, table[n], values);
if (values) {
values[n] = val;
}
if (val == Qundef) {
if (NIL_P(missing)) {
missing = rb_ary_new();
}
rb_ary_push(missing, table[n]);
rb_keyword_error("missing", missing);
}
extracted++;
}

if (optional && !NIL_P(keyword_hash)) {
for (int m = required; m < required + optional; m++) {
VALUE val = rb_tr_extract_keyword(keyword_hash, table[m], values);
if (values) {
values[m] = val;
}
if (val != Qundef) {
extracted++;
}
}
}

if (!rest && !NIL_P(keyword_hash)) {
if (RHASH_SIZE(keyword_hash) > (unsigned int)(values ? 0 : extracted)) {
unknown_keyword_error(keyword_hash, table, required + optional);
}
}

for (int i = extracted; i < required + optional; i++) {
values[i] = Qundef;
}

return extracted;
}
141 changes: 141 additions & 0 deletions src/main/c/cext/array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include <truffleruby-impl.h>

// Array, rb_ary_*

long rb_array_len(VALUE array) {
return polyglot_get_array_size(rb_tr_unwrap(array));
}

int RARRAY_LENINT(VALUE array) {
return polyglot_get_array_size(rb_tr_unwrap(array));
}

VALUE RARRAY_AREF(VALUE array, long index) {
return rb_tr_wrap(polyglot_get_array_element(rb_tr_unwrap(array), (int) index));
}

VALUE rb_Array(VALUE array) {
return RUBY_CEXT_INVOKE("rb_Array", array);
}

VALUE *RARRAY_PTR_IMPL(VALUE array) {
return (VALUE *) polyglot_as_i64_array(RUBY_CEXT_INVOKE_NO_WRAP("RARRAY_PTR", array));
}

VALUE rb_ary_new() {
return RUBY_CEXT_INVOKE("rb_ary_new");
}

VALUE rb_ary_new_capa(long capacity) {
return rb_tr_wrap(polyglot_invoke(RUBY_CEXT, "rb_ary_new_capa", capacity));
}

VALUE rb_ary_new_from_args(long n, ...) {
VALUE array = rb_ary_new_capa(n);
va_list args;
va_start(args, n);
for (int i = 0; i < n; i++) {
rb_ary_store(array, i, va_arg(args, VALUE));
}
va_end(args);
return array;
}

VALUE rb_ary_new_from_values(long n, const VALUE *values) {
VALUE array = rb_ary_new_capa(n);
for (int i = 0; i < n; i++) {
rb_ary_store(array, i, values[i]);
}
return array;
}

VALUE rb_ary_push(VALUE array, VALUE value) {
RUBY_INVOKE_NO_WRAP(array, "push", value);
return array;
}

VALUE rb_ary_pop(VALUE array) {
return RUBY_INVOKE(array, "pop");
}

void rb_ary_store(VALUE array, long index, VALUE value) {
RUBY_INVOKE_NO_WRAP(array, "[]=", LONG2FIX(index), value);
}

VALUE rb_ary_entry(VALUE array, long index) {
return rb_tr_wrap(polyglot_invoke(rb_tr_unwrap(array), "[]", index));
}

VALUE rb_ary_unshift(VALUE array, VALUE value) {
return RUBY_INVOKE(array, "unshift", value);
}

VALUE rb_ary_aref(int n, const VALUE* values, VALUE array) {
return RUBY_CEXT_INVOKE("send_splatted", array, rb_str_new_cstr("[]"), rb_ary_new4(n, values));
}

VALUE rb_ary_clear(VALUE array) {
return RUBY_INVOKE(array, "clear");
}

VALUE rb_ary_delete(VALUE array, VALUE value) {
return RUBY_INVOKE(array, "delete", value);
}

VALUE rb_ary_delete_at(VALUE array, long n) {
return rb_tr_wrap(polyglot_invoke(rb_tr_unwrap(array), "delete_at", n));
}

VALUE rb_ary_includes(VALUE array, VALUE value) {
return RUBY_INVOKE(array, "include?", value);
}

VALUE rb_ary_join(VALUE array, VALUE sep) {
return RUBY_INVOKE(array, "join", sep);
}

VALUE rb_ary_to_s(VALUE array) {
return RUBY_INVOKE(array, "to_s");
}

VALUE rb_ary_reverse(VALUE array) {
return RUBY_INVOKE(array, "reverse!");
}

VALUE rb_ary_shift(VALUE array) {
return RUBY_INVOKE(array, "shift");
}

VALUE rb_ary_concat(VALUE a, VALUE b) {
return RUBY_INVOKE(a, "concat", b);
}

VALUE rb_ary_plus(VALUE a, VALUE b) {
return RUBY_INVOKE(a, "+", b);
}

VALUE rb_ary_to_ary(VALUE array) {
VALUE tmp = rb_check_array_type(array);

if (!NIL_P(tmp)) return tmp;
return rb_ary_new_from_args(1, array);
}

VALUE rb_ary_subseq(VALUE array, long start, long length) {
return rb_tr_wrap(polyglot_invoke(rb_tr_unwrap(array), "[]", start, length));
}

VALUE rb_ary_cat(VALUE array, const VALUE *cat, long n) {
return RUBY_INVOKE(array, "concat", rb_ary_new4(n, cat));
}

VALUE rb_ary_rotate(VALUE array, long n) {
if (n != 0) {
return rb_tr_wrap(polyglot_invoke(rb_tr_unwrap(array), "rotate!", n));
}
return Qnil;
}

VALUE rb_ary_tmp_new(long capa) {
return rb_ary_new_capa(capa);
}
Loading

0 comments on commit d83ddc3

Please sign in to comment.