duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) { duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */ d = duk__toint32_touint32_helper(d, 1); DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL); DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */ DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */ return (duk_int32_t) d; }
duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) { duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */ d = duk__toint32_touint32_helper(d, 0); DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL); DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */ DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */ return (duk_uint32_t) d; }
DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) { duk_double_t d; #if defined(DUK_USE_FASTINT) if (DUK_TVAL_IS_FASTINT(tv)) { return DUK_TVAL_GET_FASTINT_I32(tv); } #endif d = duk_js_tonumber(thr, tv); /* invalidates tv */ d = duk__toint32_touint32_helper(d, 1); DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL); DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */ DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */ return (duk_int32_t) d; }
DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) { /* XXX: fastint */ duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */ return duk_js_tointeger_number(d); }
DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) { duk_context *ctx = (duk_hthread *) thr; DUK_ASSERT(thr != NULL); DUK_ASSERT(tv != NULL); switch (DUK_TVAL_GET_TAG(tv)) { case DUK_TAG_UNDEFINED: { /* return a specific NaN (although not strictly necessary) */ duk_double_union du; DUK_DBLUNION_SET_NAN(&du); DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du)); return du.d; } case DUK_TAG_NULL: { /* +0.0 */ return 0.0; } case DUK_TAG_BOOLEAN: { if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) { return 1.0; } return 0.0; } case DUK_TAG_STRING: { duk_hstring *h = DUK_TVAL_GET_STRING(tv); duk_push_hstring(ctx, h); return duk__tonumber_string_raw(thr); } case DUK_TAG_OBJECT: { /* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint), * so use [[DefaultValue]] directly. */ duk_double_t d; duk_push_tval(ctx, tv); duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */ /* recursive call for a primitive value (guaranteed not to cause second * recursion). */ d = duk_js_tonumber(thr, duk_require_tval(ctx, -1)); duk_pop(ctx); return d; } case DUK_TAG_BUFFER: { /* Coerce like a string. This makes sense because addition also treats * buffers like strings. */ duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv); duk_push_hbuffer(ctx, h); duk_to_string(ctx, -1); /* XXX: expensive, but numconv now expects to see a string */ return duk__tonumber_string_raw(thr); } case DUK_TAG_POINTER: { /* Coerce like boolean */ void *p = DUK_TVAL_GET_POINTER(tv); return (p != NULL ? 1.0 : 0.0); } case DUK_TAG_LIGHTFUNC: { /* +(function(){}) -> NaN */ return DUK_DOUBLE_NAN; } #if defined(DUK_USE_FASTINT) case DUK_TAG_FASTINT: return (duk_double_t) DUK_TVAL_GET_FASTINT(tv); #endif default: { /* number */ DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv)); return DUK_TVAL_GET_DOUBLE(tv); } } DUK_UNREACHABLE(); }
duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) { duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */ return duk_js_tointeger_number(d); }