Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

279 lines (222 sloc) 7.174 kb
#include "builtin/bignum.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/object.hpp"
#include "capi/capi.hpp"
#include "capi/18/include/ruby.h"
#include <gdtoa.h>
using namespace rubinius;
using namespace rubinius::capi;
extern "C" {
char rb_num2chr(VALUE obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(obj);
String* str;
char chr;
if((str = try_as<String>(object)) && str->size() >= 1) {
chr = str->c_str(env->state())[0];
} else {
chr = (char)(NUM2INT(obj) & 0xff);
}
return chr;
}
long rb_num2long(VALUE obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(obj);
if(object->nil_p()) {
rb_raise(rb_eTypeError, "no implicit conversion from nil to Integer");
} else if(Fixnum* fix = try_as<Fixnum>(object)) {
return fix->to_long();
} else if(try_as<Bignum>(object)) {
return rb_big2long(obj);
} else if(try_as<Float>(object)) {
return (long)capi_get_float(env, obj)->val;
} else if(object->true_p()) {
rb_raise(rb_eTypeError, "can't convert true to Integer");
} else if(object->false_p()) {
rb_raise(rb_eTypeError, "can't convert false to Integer");
}
ID to_int_id = rb_intern("to_int");
if(!rb_respond_to(obj, to_int_id)) {
rb_raise(rb_eTypeError, "can't convert %s into Integer",
rb_obj_classname(obj));
}
obj = rb_funcall(obj, to_int_id, 0);
return rb_num2long(obj);
}
unsigned long rb_num2ulong(VALUE obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(obj);
if(try_as<Bignum>(object)) {
return rb_big2ulong(obj);
}
return (unsigned long)rb_num2long(obj);
}
long long rb_num2ll(VALUE obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(obj);
if(Bignum* big = try_as<Bignum>(object)) {
return big->to_long_long();
}
return (long long)rb_num2long(obj);
}
unsigned long long rb_num2ull(VALUE obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(obj);
if(Bignum* big = try_as<Bignum>(object)) {
return big->to_ulong_long();
}
return (unsigned long long)rb_num2long(obj);
}
VALUE rb_int2big(long number) {
return capi_native2num<long>(number);
}
VALUE rb_uint2big(unsigned long number) {
return capi_native2num<unsigned long>(number);
}
VALUE rb_int2inum(long int number) {
return capi_native2num<long int>(number);
}
VALUE INT2NUM(long int number) {
return capi_native2num<long int>(number);
}
VALUE LONG2NUM(long int number) {
return capi_native2num<long int>(number);
}
VALUE rb_uint2inum(unsigned long number) {
return capi_native2num<unsigned long>(number);
}
VALUE UINT2NUM(unsigned long number) {
return capi_native2num<unsigned long>(number);
}
VALUE ULONG2NUM(unsigned long number) {
return capi_native2num<unsigned long>(number);
}
VALUE rb_cstr2inum(const char* string, int base) {
return rb_str2inum(rb_str_new2(string), base);
}
VALUE rb_cstr_to_inum(const char* str, int base, int badcheck) {
// TODO don't ignore badcheck
return rb_cstr2inum(str, base);
}
VALUE rb_ll2inum(long long val) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
return env->get_handle(Integer::from(env->state(), val));
}
VALUE rb_ull2inum(unsigned long long val) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
return env->get_handle(Integer::from(env->state(), val));
}
VALUE rb_num_coerce_bin(VALUE x, VALUE y, ID func) {
return rb_funcall(rb_mCAPI, rb_intern("rb_num_coerce_bin"), 3, x, y, ID2SYM(func));
}
VALUE rb_num_coerce_cmp(VALUE x, VALUE y, ID func) {
return rb_funcall(rb_mCAPI, rb_intern("rb_num_coerce_cmp"), 3, x, y, ID2SYM(func));
}
double rb_num2dbl(VALUE val) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Object* object = env->get_object(val);
if(object->nil_p()) {
rb_raise(rb_eTypeError, "no implicit conversion from nil to Float");
} else if(try_as<String>(object)) {
rb_raise(rb_eTypeError, "no implicit conversion from String to Float");
} else if(!try_as<Float>(object)) {
val = rb_Float(val);
}
return capi_get_float(env, val)->val;
}
// Imported from MRI
double rb_cstr_to_dbl(const char *p, int badcheck) {
const char *q;
char *end;
double d;
const char *ellipsis = "";
int w;
#define OutOfRange() (((w = end - p) > 20) ? (w = 20, ellipsis = "...") : (ellipsis = ""))
if (!p) return 0.0;
q = p;
while (ISSPACE(*p)) p++;
d = ::ruby_strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
rb_warning("Float %.*s%s out of range", w, p, ellipsis);
errno = 0;
}
if (p == end) {
if (badcheck) {
bad:
rb_invalid_str(q, "Float()");
}
return d;
}
if (*end) {
char buf[DBL_DIG * 4 + 10];
char *n = buf;
char *e = buf + sizeof(buf) - 1;
char prev = 0;
while (p < end && n < e) prev = *n++ = *p++;
while (*p) {
if (*p == '_') {
/* remove underscores between digits */
if (badcheck) {
if (n == buf || !ISDIGIT(prev)) goto bad;
++p;
if (!ISDIGIT(*p)) goto bad;
} else {
while (*++p == '_');
continue;
}
}
prev = *p++;
if (n < e) *n++ = prev;
}
*n = '\0';
p = buf;
d = ::ruby_strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
rb_warning("Float %.*s%s out of range", w, p, ellipsis);
errno = 0;
}
if (badcheck) {
if (!end || p == end) goto bad;
while (*end && ISSPACE(*end)) end++;
if (*end) goto bad;
}
}
if (errno == ERANGE) {
errno = 0;
OutOfRange();
rb_raise(rb_eArgError, "Float %.*s%s out of range", w, q, ellipsis);
}
return d;
}
VALUE rb_Integer(VALUE object_handle) {
return rb_convert_type(object_handle, 0, "Integer", "to_i");
}
void rb_num_zerodiv(void) {
rb_raise(rb_eZeroDivError, "divided by 0");
}
int rb_cmpint(VALUE val, VALUE a, VALUE b) {
if(NIL_P(val)) rb_cmperr(a, b);
if(FIXNUM_P(val)) return FIX2INT(val);
if(TYPE(val) == T_BIGNUM) {
if(RBIGNUM_SIGN(val)) return 1;
return -1;
}
if(RTEST(rb_funcall(val, rb_intern(">"), 1, INT2FIX(0)))) return 1;
if(RTEST(rb_funcall(val, rb_intern("<"), 1, INT2FIX(0)))) return -1;
return 0;
}
void rb_cmperr(VALUE x, VALUE y) {
const char *classname;
if(SPECIAL_CONST_P(y)) {
y = rb_inspect(y);
classname = StringValuePtr(y);
} else {
classname = rb_obj_classname(y);
}
rb_raise(rb_eArgError, "comparison of %s with %s failed",
rb_obj_classname(x), classname);
}
}
Jump to Line
Something went wrong with that request. Please try again.