static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; TRACE("\n"); if(!(number = number_this(jsthis))) return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); if(r) *r = jsval_number(number->value); return S_OK; }
static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { NumberInstance *number; TRACE("\n"); if(!(number = number_this(jsthis))) return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL); if(retv) *retv = number->num; return S_OK; }
static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; INT prec = 0, size; jsstr_t *str; DOUBLE val; HRESULT hres; if(!(number = number_this(jsthis))) return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); if(argc) { hres = to_int32(ctx, argv[0], &prec); if(FAILED(hres)) return hres; if(prec<1 || prec>21) return throw_range_error(ctx, JS_E_PRECISION_OUT_OF_RANGE, NULL); } val = number->value; if(isinf(val) || isnan(val) || !prec) { hres = to_string(ctx, jsval_number(val), &str); if(FAILED(hres)) return hres; } else { if(val != 0) size = floor(log10(val>0 ? val : -val)) + 1; else size = 1; if(size > prec) str = number_to_exponential(val, prec-1); else str = number_to_fixed(val, prec-size); if(!str) return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else jsstr_release(str); return S_OK; }
static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; DOUBLE val; INT prec = 0; jsstr_t *str; HRESULT hres; TRACE("\n"); if(!(number = number_this(jsthis))) return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); if(argc) { hres = to_int32(ctx, argv[0], &prec); if(FAILED(hres)) return hres; if(prec<0 || prec>20) return throw_range_error(ctx, JS_E_FRACTION_DIGITS_OUT_OF_RANGE, NULL); } val = number->value; if(isinf(val) || isnan(val)) { hres = to_string(ctx, jsval_number(val), &str); if(FAILED(hres)) return hres; } else { if(!prec) prec--; str = number_to_exponential(val, prec); if(!str) return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else jsstr_release(str); return S_OK; }
/* ECMA-262 3rd Edition 15.7.4.2 */ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { NumberInstance *number; INT radix = 10; DOUBLE val; jsstr_t *str; HRESULT hres; TRACE("\n"); if(!(number = number_this(jsthis))) return throw_type_error(ctx, JS_E_NUMBER_EXPECTED, NULL); if(argc) { hres = to_int32(ctx, argv[0], &radix); if(FAILED(hres)) return hres; if(radix<2 || radix>36) return throw_type_error(ctx, JS_E_INVALIDARG, NULL); } val = number->value; if(radix==10 || isnan(val) || isinf(val)) { hres = to_string(ctx, jsval_number(val), &str); if(FAILED(hres)) return hres; } else { INT idx = 0; DOUBLE integ, frac, log_radix = 0; WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16]; BOOL exp = FALSE; if(val<0) { val = -val; buf[idx++] = '-'; } while(1) { integ = floor(val); frac = val-integ; if(integ == 0) buf[idx++] = '0'; while(integ>=1 && idx<NUMBER_TOSTRING_BUF_SIZE) { buf[idx] = fmod(integ, radix); if(buf[idx]<10) buf[idx] += '0'; else buf[idx] += 'a'-10; integ /= radix; idx++; } if(idx<NUMBER_TOSTRING_BUF_SIZE) { INT beg = buf[0]=='-'?1:0; INT end = idx-1; WCHAR wch; while(end > beg) { wch = buf[beg]; buf[beg++] = buf[end]; buf[end--] = wch; } } if(idx != NUMBER_TOSTRING_BUF_SIZE) buf[idx++] = '.'; while(frac>0 && idx<NUMBER_TOSTRING_BUF_SIZE) { frac *= radix; buf[idx] = fmod(frac, radix); frac -= buf[idx]; if(buf[idx]<10) buf[idx] += '0'; else buf[idx] += 'a'-10; idx++; } if(idx==NUMBER_TOSTRING_BUF_SIZE && !exp) { exp = TRUE; idx = (buf[0]=='-') ? 1 : 0; log_radix = floor(log(val)/log(radix)); val *= pow(radix, -log_radix); continue; } break; } while(buf[idx-1] == '0') idx--; if(buf[idx-1] == '.') idx--; if(exp) { if(log_radix==0) buf[idx] = 0; else { static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0}; WCHAR ch; if(log_radix<0) { log_radix = -log_radix; ch = '-'; } else ch = '+'; sprintfW(&buf[idx], formatW, ch, (int)log_radix); } } else buf[idx] = '\0'; str = jsstr_alloc(buf); if(!str) return E_OUTOFMEMORY; } if(r) *r = jsval_string(str); else jsstr_release(str); return S_OK; }
/* ECMA-262 3rd Edition 15.7.4.2 */ static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { NumberInstance *number; INT radix = 10; DOUBLE val; BSTR str; HRESULT hres; TRACE("\n"); if(!(number = number_this(jsthis))) return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL); if(arg_cnt(dp)) { hres = to_int32(ctx, get_arg(dp, 0), ei, &radix); if(FAILED(hres)) return hres; if(radix<2 || radix>36) return throw_type_error(ctx, ei, IDS_INVALID_CALL_ARG, NULL); } if(V_VT(&number->num) == VT_I4) val = V_I4(&number->num); else val = V_R8(&number->num); if(radix==10 || isnan(val) || isinf(val)) { hres = to_string(ctx, &number->num, ei, &str); if(FAILED(hres)) return hres; } else { INT idx = 0; DOUBLE integ, frac, log_radix = 0; WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16]; BOOL exp = FALSE; if(val<0) { val = -val; buf[idx++] = '-'; } while(1) { integ = floor(val); frac = val-integ; if(integ == 0) buf[idx++] = '0'; while(integ>=1 && idx<NUMBER_TOSTRING_BUF_SIZE) { buf[idx] = fmod(integ, radix); if(buf[idx]<10) buf[idx] += '0'; else buf[idx] += 'a'-10; integ /= radix; idx++; } if(idx<NUMBER_TOSTRING_BUF_SIZE) { INT beg = buf[0]=='-'?1:0; INT end = idx-1; WCHAR wch; while(end > beg) { wch = buf[beg]; buf[beg++] = buf[end]; buf[end--] = wch; } } if(idx != NUMBER_TOSTRING_BUF_SIZE) buf[idx++] = '.'; while(frac>0 && idx<NUMBER_TOSTRING_BUF_SIZE) { frac *= radix; buf[idx] = fmod(frac, radix); frac -= buf[idx]; if(buf[idx]<10) buf[idx] += '0'; else buf[idx] += 'a'-10; idx++; } if(idx==NUMBER_TOSTRING_BUF_SIZE && !exp) { exp = TRUE; idx = (buf[0]=='-') ? 1 : 0; log_radix = floor(log(val)/log(radix)); val *= pow(radix, -log_radix); continue; } break; } while(buf[idx-1] == '0') idx--; if(buf[idx-1] == '.') idx--; if(exp) { if(log_radix==0) buf[idx++] = '\0'; else { static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0}; WCHAR ch; if(log_radix<0) { log_radix = -log_radix; ch = '-'; } else ch = '+'; sprintfW(&buf[idx], formatW, ch, (int)log_radix); } } else buf[idx] = '\0'; str = SysAllocString(buf); if(!str) return E_OUTOFMEMORY; } if(retv) { V_VT(retv) = VT_BSTR; V_BSTR(retv) = str; }else { SysFreeString(str); } return S_OK; }