* ext/bigdecimal/bigdecimal.c (BigDecimal_s_allocate): follow

Allocation Framework.  [Bug #5775]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34089 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2011-12-21 03:35:27 +00:00
Родитель 1c6226b67d
Коммит f9a4d5717c
4 изменённых файлов: 95 добавлений и 29 удалений

Просмотреть файл

@ -1,3 +1,8 @@
Wed Dec 21 12:35:24 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c (BigDecimal_s_allocate): follow
Allocation Framework. [Bug #5775]
Wed Dec 21 02:25:36 2011 Aaron Patterson <aaron@tenderlovemaking.com>
* ext/psych/emitter.c: fixing clang warnings. Thanks Joey!

Просмотреть файл

@ -131,7 +131,7 @@ static unsigned short VpGetException(void);
static void VpSetException(unsigned short f);
static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
static int VpLimitRound(Real *c, size_t ixDigit);
static Real *VpDup(Real const* const x);
static Real *VpCopy(Real *pv, Real const* const x);
/*
* **** BigDecimal part ****
@ -561,15 +561,14 @@ VpCreateRbObject(size_t mx, const char *str)
}
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
#define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
static Real *
VpDup(Real const* const x)
VpCopy(Real *pv, Real const* const x)
{
Real *pv;
assert(x != NULL);
pv = VpAllocReal(x->MaxPrec);
pv = VpReallocReal(pv, x->MaxPrec);
pv->MaxPrec = x->MaxPrec;
pv->Prec = x->Prec;
pv->exponent = x->exponent;
@ -577,9 +576,6 @@ VpDup(Real const* const x)
pv->flag = x->flag;
MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
pv->obj = TypedData_Wrap_Struct(
rb_obj_class(x->obj), &BigDecimal_data_type, pv);
return pv;
}
@ -2254,6 +2250,14 @@ BigDecimal_power_op(VALUE self, VALUE exp)
return BigDecimal_power(1, &exp, self);
}
static VALUE
BigDecimal_s_allocate(VALUE klass)
{
return VpNewRbClass(0, NULL, klass)->obj;
}
static Real *BigDecimal_new(int argc, VALUE *argv);
/* call-seq:
* new(initial, digits)
*
@ -2272,10 +2276,36 @@ BigDecimal_power_op(VALUE self, VALUE exp)
* larger than the specified number.
*/
static VALUE
BigDecimal_new(int argc, VALUE *argv, VALUE self)
BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
{
Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
Real *x = BigDecimal_new(argc, argv);
if (ToValue(x)) {
pv = VpCopy(pv, x);
}
else {
VpFree(pv);
pv = x;
}
DATA_PTR(self) = pv;
pv->obj = self;
return self;
}
static VALUE
BigDecimal_initialize_copy(VALUE self, VALUE other)
{
Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
DATA_PTR(self) = VpCopy(pv, x);
return self;
}
static Real *
BigDecimal_new(int argc, VALUE *argv)
{
ENTER(5);
Real *pv;
size_t mf;
VALUE nFig;
VALUE iniValue;
@ -2290,15 +2320,14 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
switch (TYPE(iniValue)) {
case T_DATA:
if (is_kind_of_BigDecimal(iniValue)) {
pv = VpDup(DATA_PTR(iniValue));
return ToValue(pv);
return DATA_PTR(iniValue);
}
break;
case T_FIXNUM:
/* fall through */
case T_BIGNUM:
return ToValue(GetVpValue(iniValue, 1));
return GetVpValue(iniValue, 1);
case T_FLOAT:
if (mf > DBL_DIG+1) {
@ -2309,23 +2338,25 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
if (NIL_P(nFig)) {
rb_raise(rb_eArgError, "can't omit precision for a Rational.");
}
return ToValue(GetVpValueWithPrec(iniValue, mf, 1));
return GetVpValueWithPrec(iniValue, mf, 1);
case T_STRING:
/* fall through */
default:
break;
}
SafeStringValue(iniValue);
GUARD_OBJ(pv, VpNewRbClass(mf, RSTRING_PTR(iniValue),self));
return ToValue(pv);
StringValueCStr(iniValue);
rb_check_safe_obj(iniValue);
return VpAlloc(mf, RSTRING_PTR(iniValue));
}
static VALUE
BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
{
return BigDecimal_new(argc, argv, rb_cBigDecimal);
Real *pv = BigDecimal_new(argc, argv);
if (ToValue(pv)) pv = VpCopy(NULL, pv);
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
return pv->obj;
}
/* call-seq:
@ -2830,16 +2861,12 @@ Init_bigdecimal(void)
/* Class and method registration */
rb_cBigDecimal = rb_define_class("BigDecimal",rb_cNumeric);
rb_undef_alloc_func(rb_cBigDecimal); /* TODO: define alloc func */
rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
/* Global function */
rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
/* Class methods */
#if 1
/* TODO: follow allocation framework */
rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_new, -1);
#endif
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
@ -2963,6 +2990,8 @@ Init_bigdecimal(void)
/* instance methods */
rb_define_method(rb_cBigDecimal, "initialize", BigDecimal_initialize, -1);
rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
@ -3093,6 +3122,16 @@ VpMemAlloc(size_t mb)
return p;
}
VP_EXPORT void *
VpMemRealloc(void *ptr, size_t mb)
{
void *p = xrealloc(ptr, mb);
if (!p) {
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
}
return p;
}
VP_EXPORT void
VpFree(Real *pv)
{

Просмотреть файл

@ -21,6 +21,9 @@
#if defined(__cplusplus)
extern "C" {
#if 0
}
#endif
#endif
#ifndef HAVE_LABS
@ -197,6 +200,7 @@ VP_EXPORT int VpIsNegDoubleZero(double v);
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
VP_EXPORT size_t VpInit(BDIGIT BaseVal);
VP_EXPORT void *VpMemAlloc(size_t mb);
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
VP_EXPORT void VpFree(Real *pv);
VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal);
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
@ -279,6 +283,9 @@ VP_EXPORT int VPrint(FILE *fp,const char *cntl_chr,Real *a);
#endif /* BIGDECIMAL_DEBUG */
#if defined(__cplusplus)
#if 0
{
#endif
} /* extern "C" { */
#endif
#endif /* RUBY_BIG_DECIMAL_H */

Просмотреть файл

@ -19,10 +19,6 @@ class TestBigDecimal < Test::Unit::TestCase
[ BigDecimal::ROUND_FLOOR, :floor],
]
def assert_allocate
assert_raise(TypeError) {BigDecimal.allocate}
end
def assert_nan(x)
assert(x.nan?, "Expected #{x.inspect} to be NaN")
end
@ -47,6 +43,10 @@ class TestBigDecimal < Test::Unit::TestCase
"Expected #{x.inspect} to be negative zero")
end
def test_not_equal
assert_not_equal BigDecimal("1"), BigDecimal.allocate
end
def test_global_new
assert_equal(1, BigDecimal("1"))
assert_equal(1, BigDecimal("1", 1))
@ -1288,4 +1288,19 @@ class TestBigDecimal < Test::Unit::TestCase
end
end
end
def test_dup
[1, -1, 2**100, -2**100].each do |i|
x = BigDecimal(i)
assert_equal(x, x.dup)
end
end
def test_dup_subclass
c = Class.new(BigDecimal)
x = c.new(1)
y = x.dup
assert_equal(1, y)
assert_kind_of(c, y)
end
end