Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 053e1e9151ba
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 81e5794b265c
Choose a head ref
  • 7 commits
  • 7 files changed
  • 1 contributor

Commits on May 13, 2015

  1. Copy the full SHA
    bf0a6b9 View commit details
  2. Copy the full SHA
    47b0b6c View commit details
  3. Copy the full SHA
    41cebe1 View commit details
  4. Added rb_vsprintf.

    brixen committed May 13, 2015
    Copy the full SHA
    1f9a63a View commit details
  5. Added rb_absint_size.

    brixen committed May 13, 2015
    Copy the full SHA
    c539381 View commit details
  6. Copy the full SHA
    de3b0e9 View commit details
  7. Update bundler to 1.9.7.

    brixen committed May 13, 2015
    Copy the full SHA
    81e5794 View commit details
Showing with 149 additions and 7 deletions.
  1. +2 −2 gems_list.txt
  2. +3 −0 spec/ruby/optional/capi/ext/rubyspec.h
  3. +47 −0 spec/ruby/optional/capi/ext/string_spec.c
  4. +23 −0 spec/ruby/optional/capi/string_spec.rb
  5. +24 −0 vm/capi/integer.cpp
  6. +43 −0 vm/capi/string.cpp
  7. +7 −5 vm/include/capi/ruby/ruby.h
4 changes: 2 additions & 2 deletions gems_list.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
bundler-1.9.4.gem
bundler-1.9.7.gem
daedalus-core-0.3.0.gem
ffi2-generators-0.1.1.gem
json-1.8.2.gem
@@ -71,7 +71,7 @@ rubysl-nkf-2.0.1.gem
rubysl-observer-2.0.0.gem
rubysl-open-uri-2.0.0.gem
rubysl-open3-2.0.0.gem
rubysl-openssl-2.2.1.gem
rubysl-openssl-2.3.0.gem
rubysl-optparse-2.0.1.gem
rubysl-ostruct-2.0.4.gem
rubysl-pathname-2.1.0.gem
3 changes: 3 additions & 0 deletions spec/ruby/optional/capi/ext/rubyspec.h
Original file line number Diff line number Diff line change
@@ -538,6 +538,8 @@
#define HAVE_RB_SECURE 1

/* String */
#define HAVE_RB_ALLOC_TMP_BUFFER 1
#define HAVE_RB_FREE_TMP_BUFFER 1
#define HAVE_RB_CSTR2INUM 1
#define HAVE_RB_CSTR_TO_INUM 1
#define HAVE_RB_STR2CSTR 1
@@ -588,6 +590,7 @@
#define HAVE_RB_STR_LENGTH 1
#define HAVE_RB_STR_EQUAL 1
#define HAVE_RB_STR_SUBSEQ 1
#define HAVE_RB_VSPRINTF 1
#endif

/* Struct */
47 changes: 47 additions & 0 deletions spec/ruby/optional/capi/ext/string_spec.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <string.h>
#include <stdarg.h>

#include "ruby.h"
#include "rubyspec.h"
@@ -11,6 +12,23 @@
extern "C" {
#endif

#ifdef HAVE_RB_ALLOC_TMP_BUFFER
VALUE string_spec_rb_alloc_tmp_buffer(VALUE self, VALUE len) {
VALUE str;

char* s = (char*)rb_alloc_tmp_buffer(&str, FIX2INT(len));

return str;
}
#endif

#ifdef HAVE_RB_FREE_TMP_BUFFER
VALUE string_spec_rb_free_tmp_buffer(VALUE self, VALUE str) {
rb_free_tmp_buffer(&str);
return str == 0 ? Qnil : Qfalse;
}
#endif

#ifdef HAVE_RB_CSTR2INUM
VALUE string_spec_rb_cstr2inum(VALUE self, VALUE str, VALUE inum) {
int num = FIX2INT(inum);
@@ -571,6 +589,23 @@ static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE r
}
#endif

#ifdef HAVE_RB_VSPRINTF
static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) {
va_list varargs;

va_start(varargs, fmt);
VALUE str = rb_vsprintf(fmt, varargs);
va_end(varargs);

return str;
}

static VALUE string_spec_rb_vsprintf(VALUE self, VALUE fmt, VALUE str, VALUE i, VALUE f) {
return string_spec_rb_vsprintf_worker(RSTRING_PTR(fmt), RSTRING_PTR(str),
FIX2INT(i), RFLOAT_VALUE(f));
}
#endif

#ifdef HAVE_RB_STR_EQUAL
VALUE string_spec_rb_str_equal(VALUE self, VALUE str1, VALUE str2) {
return rb_str_equal(str1, str2);
@@ -593,6 +628,14 @@ void Init_string_spec() {
VALUE cls;
cls = rb_define_class("CApiStringSpecs", rb_cObject);

#ifdef HAVE_RB_ALLOC_TMP_BUFFER
rb_define_method(cls, "rb_alloc_tmp_buffer", string_spec_rb_alloc_tmp_buffer, 1);
#endif

#ifdef HAVE_RB_FREE_TMP_BUFFER
rb_define_method(cls, "rb_free_tmp_buffer", string_spec_rb_free_tmp_buffer, 1);
#endif

#ifdef HAVE_RB_CSTR2INUM
rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2);
#endif
@@ -827,6 +870,10 @@ void Init_string_spec() {
rb_define_method(cls, "rb_sprintf2", string_spec_rb_sprintf2, 3);
#endif

#ifdef HAVE_RB_VSPRINTF
rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4);
#endif

#ifdef HAVE_RB_STR_EQUAL
rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2);
#endif
23 changes: 23 additions & 0 deletions spec/ruby/optional/capi/string_spec.rb
Original file line number Diff line number Diff line change
@@ -766,4 +766,27 @@ def to_str
@s.rb_sprintf2(s, "string", "content").should == "Awesome string is here with content"
end
end

describe "rb_vsprintf" do
it "returns a formatted String from a variable number of arguments" do
s = @s.rb_vsprintf("%s, %d, %.2f", "abc", 42, 2.7);
s.should == "abc, 42, 2.70"
end
end

describe "rb_alloc_tmp_buffer" do
it "creates a String and returns an address" do
s = @s.rb_alloc_tmp_buffer(5)
s.should be_an_instance_of(String)
s.size.should == 5
end
end

describe "rb_free_tmp_buffer" do
it "clears a String" do
s = "abc"
@s.rb_free_tmp_buffer(s)
s.size.should == 0
end
end
end
24 changes: 24 additions & 0 deletions vm/capi/integer.cpp
Original file line number Diff line number Diff line change
@@ -7,6 +7,30 @@ using namespace rubinius;
using namespace rubinius::capi;

extern "C" {
/* This is a really wacky MRI API, which is actually marked internal
* despite being used in external code. The existing Fixnum#size and
* Bignum#size methods are sufficient for the 3-4 places it's used in MRI's
* code itself, where the 2nd argument isn't even used.
*
* We provide a "good enough" implementation.
*/
size_t rb_absint_size(VALUE value, int* nlz_bits) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
size_t size = 0;

if(RB_TYPE_P(value, T_FIXNUM)) {
size = FIXNUM_WIDTH;
} else if(RB_TYPE_P(value, T_BIGNUM)) {
Bignum* big = c_as<Bignum>(env->get_object(value));
size = big->size(env->state())->to_native();
}

// Within bounds
if(nlz_bits) *nlz_bits = 0;

return size;
}

int rb_integer_pack(VALUE value, void *words, size_t numwords, size_t wordsize,
size_t nails, int flags)
{
43 changes: 43 additions & 0 deletions vm/capi/string.cpp
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#include "util/vsnprintf.h"

#include <string.h>
#include <sys/mman.h>

using namespace rubinius;
using namespace rubinius::capi;
@@ -166,6 +167,27 @@ extern "C" {
return handle->as_rstring(env, cache_level);
}

void* rb_alloc_tmp_buffer(VALUE* store, long len) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

VALUE s = env->get_handle(String::create_pinned(env->state(), Fixnum::from(len)));
*store = s;

return RSTRING_PTR(s);
}

void rb_free_tmp_buffer(VALUE* store)
{
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

VALUE s = *store;
*store = 0;

String* str = c_as<String>(env->get_object(s));
str->num_bytes(env->state(), 0);
str->data(env->state(), ByteArray::create(env->state(), 1));
}

void rb_str_modify(VALUE self) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

@@ -641,4 +663,25 @@ extern "C" {
rb_str_set_len(result, err);
return result;
}

#define RBX_RB_VSPRINTF_LEN 0x10000

VALUE rb_vsprintf(const char *format, va_list varargs) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

void* buffer = mmap(NULL, RBX_RB_VSPRINTF_LEN,
PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);

if(buffer == MAP_FAILED) {
return env->get_handle(String::create(env->state(),
"rb_vsprintf failed to allocate space for result"));
}

native_int length = vsnprintf((char*)buffer, RBX_RB_VSPRINTF_LEN, format, varargs);
String* str = String::create(env->state(), (const char*)buffer, length);

munmap(buffer, RBX_RB_VSPRINTF_LEN);

return env->get_handle(str);
}
}
12 changes: 7 additions & 5 deletions vm/include/capi/ruby/ruby.h
Original file line number Diff line number Diff line change
@@ -565,11 +565,7 @@ struct RFile {
#define ZALLOC_N(type,n) ((type*)xcalloc((n),sizeof(type)))
#define ZALLOC(type) (ZALLOC_N(type,1))

#ifdef C_ALLOCA
# define ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n))
#else
# define ALLOCV(v, n) ((n) < 1024 ? (RB_GC_GUARD(v) = 0, alloca(n)) : rb_alloc_tmp_buffer(&(v), (n)))
#endif
#define ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n))
#define ALLOCV_N(type, v, n) ((type*)ALLOCV((v), sizeof(type)*(n)))
#define ALLOCV_END(v) rb_free_tmp_buffer(&(v))

@@ -1087,6 +1083,8 @@ struct RTypedData {

VALUE rb_iterate(VALUE (*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data);

size_t rb_absint_size(VALUE value, int* nlz_bits);

VALUE rb_big2str(VALUE self, int base);

long rb_big2long(VALUE obj);
@@ -1856,6 +1854,9 @@ struct RTypedData {
/** Returns a String in locale encoding. */
VALUE rb_locale_str_new(const char* string, long len);

void* rb_alloc_tmp_buffer(VALUE* s, long len);
void rb_free_tmp_buffer(VALUE* s);

VALUE rb_str_export(VALUE);
VALUE rb_str_export_locale(VALUE);

@@ -2020,6 +2021,7 @@ struct RTypedData {
void rb_str_free(VALUE str);

VALUE rb_sprintf(const char* format, ...);
VALUE rb_vsprintf(const char *format, va_list varargs);

VALUE rb_str_equal(VALUE self, VALUE other);