ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

number.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 Jacek Caban for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 #include "wine/port.h"
00021 
00022 #include <math.h>
00023 
00024 #include "jscript.h"
00025 
00026 #include "wine/debug.h"
00027 
00028 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
00029 
00030 typedef struct {
00031     DispatchEx dispex;
00032 
00033     VARIANT num;
00034 } NumberInstance;
00035 
00036 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
00037 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
00038 static const WCHAR toFixedW[] = {'t','o','F','i','x','e','d',0};
00039 static const WCHAR toExponentialW[] = {'t','o','E','x','p','o','n','e','n','t','i','a','l',0};
00040 static const WCHAR toPrecisionW[] = {'t','o','P','r','e','c','i','s','i','o','n',0};
00041 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
00042 
00043 #define NUMBER_TOSTRING_BUF_SIZE 64
00044 
00045 static inline NumberInstance *number_from_vdisp(vdisp_t *vdisp)
00046 {
00047     return (NumberInstance*)vdisp->u.jsdisp;
00048 }
00049 
00050 static inline NumberInstance *number_this(vdisp_t *jsthis)
00051 {
00052     return is_vclass(jsthis, JSCLASS_NUMBER) ? number_from_vdisp(jsthis) : NULL;
00053 }
00054 
00055 /* ECMA-262 3rd Edition    15.7.4.2 */
00056 static HRESULT Number_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00057         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00058 {
00059     NumberInstance *number;
00060     INT radix = 10;
00061     DOUBLE val;
00062     BSTR str;
00063     HRESULT hres;
00064 
00065     TRACE("\n");
00066 
00067     if(!(number = number_this(jsthis)))
00068         return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL);
00069 
00070     if(arg_cnt(dp)) {
00071         hres = to_int32(ctx, get_arg(dp, 0), ei, &radix);
00072         if(FAILED(hres))
00073             return hres;
00074 
00075         if(radix<2 || radix>36)
00076             return throw_type_error(ctx, ei, IDS_INVALID_CALL_ARG, NULL);
00077     }
00078 
00079     if(V_VT(&number->num) == VT_I4)
00080         val = V_I4(&number->num);
00081     else
00082         val = V_R8(&number->num);
00083 
00084     if(radix==10 || isnan(val) || isinf(val)) {
00085         hres = to_string(ctx, &number->num, ei, &str);
00086         if(FAILED(hres))
00087             return hres;
00088     }
00089     else {
00090         INT idx = 0;
00091         DOUBLE integ, frac, log_radix = 0;
00092         WCHAR buf[NUMBER_TOSTRING_BUF_SIZE+16];
00093         BOOL exp = FALSE;
00094 
00095         if(val<0) {
00096             val = -val;
00097             buf[idx++] = '-';
00098         }
00099 
00100         while(1) {
00101             integ = floor(val);
00102             frac = val-integ;
00103 
00104             if(integ == 0)
00105                 buf[idx++] = '0';
00106             while(integ>=1 && idx<NUMBER_TOSTRING_BUF_SIZE) {
00107                 buf[idx] = fmod(integ, radix);
00108                 if(buf[idx]<10) buf[idx] += '0';
00109                 else buf[idx] += 'a'-10;
00110                 integ /= radix;
00111                 idx++;
00112             }
00113 
00114             if(idx<NUMBER_TOSTRING_BUF_SIZE) {
00115                 INT beg = buf[0]=='-'?1:0;
00116                 INT end = idx-1;
00117                 WCHAR wch;
00118 
00119                 while(end > beg) {
00120                     wch = buf[beg];
00121                     buf[beg++] = buf[end];
00122                     buf[end--] = wch;
00123                 }
00124             }
00125 
00126             if(idx != NUMBER_TOSTRING_BUF_SIZE) buf[idx++] = '.';
00127 
00128             while(frac>0 && idx<NUMBER_TOSTRING_BUF_SIZE) {
00129                 frac *= radix;
00130                 buf[idx] = fmod(frac, radix);
00131                 frac -= buf[idx];
00132                 if(buf[idx]<10) buf[idx] += '0';
00133                 else buf[idx] += 'a'-10;
00134                 idx++;
00135             }
00136 
00137             if(idx==NUMBER_TOSTRING_BUF_SIZE && !exp) {
00138                 exp = TRUE;
00139                 idx = (buf[0]=='-') ? 1 : 0;
00140                 log_radix = floor(log(val)/log(radix));
00141                 val *= pow(radix, -log_radix);
00142                 continue;
00143             }
00144 
00145             break;
00146         }
00147 
00148         while(buf[idx-1] == '0') idx--;
00149         if(buf[idx-1] == '.') idx--;
00150 
00151         if(exp) {
00152             if(log_radix==0)
00153                 buf[idx++] = '\0';
00154             else {
00155                 static const WCHAR formatW[] = {'(','e','%','c','%','d',')',0};
00156                 WCHAR ch;
00157 
00158                 if(log_radix<0) {
00159                     log_radix = -log_radix;
00160                     ch = '-';
00161                 }
00162                 else ch = '+';
00163                 sprintfW(&buf[idx], formatW, ch, (int)log_radix);
00164             }
00165         }
00166         else buf[idx] = '\0';
00167 
00168         str = SysAllocString(buf);
00169         if(!str)
00170             return E_OUTOFMEMORY;
00171     }
00172 
00173     if(retv) {
00174         V_VT(retv) = VT_BSTR;
00175         V_BSTR(retv) = str;
00176     }else {
00177         SysFreeString(str);
00178     }
00179     return S_OK;
00180 }
00181 
00182 static HRESULT Number_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00183         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00184 {
00185     FIXME("\n");
00186     return E_NOTIMPL;
00187 }
00188 
00189 static HRESULT Number_toFixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00190         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00191 {
00192     FIXME("\n");
00193     return E_NOTIMPL;
00194 }
00195 
00196 static HRESULT Number_toExponential(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00197         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00198 {
00199     FIXME("\n");
00200     return E_NOTIMPL;
00201 }
00202 
00203 static HRESULT Number_toPrecision(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00204         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00205 {
00206     FIXME("\n");
00207     return E_NOTIMPL;
00208 }
00209 
00210 static HRESULT Number_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00211         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00212 {
00213     NumberInstance *number;
00214 
00215     TRACE("\n");
00216 
00217     if(!(number = number_this(jsthis)))
00218         return throw_type_error(ctx, ei, IDS_NOT_NUM, NULL);
00219 
00220     if(retv)
00221         *retv = number->num;
00222     return S_OK;
00223 }
00224 
00225 static HRESULT Number_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00226         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00227 {
00228     NumberInstance *number = number_from_vdisp(jsthis);
00229 
00230     switch(flags) {
00231     case INVOKE_FUNC:
00232         return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
00233     case DISPATCH_PROPERTYGET:
00234         *retv = number->num;
00235         break;
00236 
00237     default:
00238         FIXME("flags %x\n", flags);
00239         return E_NOTIMPL;
00240     }
00241 
00242     return S_OK;
00243 }
00244 
00245 static const builtin_prop_t Number_props[] = {
00246     {toExponentialW,         Number_toExponential,         PROPF_METHOD|1},
00247     {toFixedW,               Number_toFixed,               PROPF_METHOD},
00248     {toLocaleStringW,        Number_toLocaleString,        PROPF_METHOD},
00249     {toPrecisionW,           Number_toPrecision,           PROPF_METHOD|1},
00250     {toStringW,              Number_toString,              PROPF_METHOD|1},
00251     {valueOfW,               Number_valueOf,               PROPF_METHOD}
00252 };
00253 
00254 static const builtin_info_t Number_info = {
00255     JSCLASS_NUMBER,
00256     {NULL, Number_value, 0},
00257     sizeof(Number_props)/sizeof(*Number_props),
00258     Number_props,
00259     NULL,
00260     NULL
00261 };
00262 
00263 static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00264         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00265 {
00266     VARIANT num;
00267     HRESULT hres;
00268 
00269     TRACE("\n");
00270 
00271     switch(flags) {
00272     case INVOKE_FUNC:
00273         if(!arg_cnt(dp)) {
00274             if(retv) {
00275                 V_VT(retv) = VT_I4;
00276                 V_I4(retv) = 0;
00277             }
00278             return S_OK;
00279         }
00280 
00281         hres = to_number(ctx, get_arg(dp, 0), ei, &num);
00282         if(FAILED(hres))
00283             return hres;
00284 
00285         if(retv)
00286             *retv = num;
00287         break;
00288 
00289     case DISPATCH_CONSTRUCT: {
00290         DispatchEx *obj;
00291 
00292         if(arg_cnt(dp)) {
00293             hres = to_number(ctx, get_arg(dp, 0), ei, &num);
00294             if(FAILED(hres))
00295                 return hres;
00296         }else {
00297             V_VT(&num) = VT_I4;
00298             V_I4(&num) = 0;
00299         }
00300 
00301         hres = create_number(ctx, &num, &obj);
00302         if(FAILED(hres))
00303             return hres;
00304 
00305         V_VT(retv) = VT_DISPATCH;
00306         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(obj);
00307         break;
00308     }
00309     default:
00310         FIXME("unimplemented flags %x\n", flags);
00311         return E_NOTIMPL;
00312     }
00313 
00314     return S_OK;
00315 }
00316 
00317 static HRESULT alloc_number(script_ctx_t *ctx, DispatchEx *object_prototype, NumberInstance **ret)
00318 {
00319     NumberInstance *number;
00320     HRESULT hres;
00321 
00322     number = heap_alloc_zero(sizeof(NumberInstance));
00323     if(!number)
00324         return E_OUTOFMEMORY;
00325 
00326     if(object_prototype)
00327         hres = init_dispex(&number->dispex, ctx, &Number_info, object_prototype);
00328     else
00329         hres = init_dispex_from_constr(&number->dispex, ctx, &Number_info, ctx->number_constr);
00330     if(FAILED(hres))
00331         return hres;
00332 
00333     *ret = number;
00334     return S_OK;
00335 }
00336 
00337 HRESULT create_number_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
00338 {
00339     NumberInstance *number;
00340     HRESULT hres;
00341 
00342     static const WCHAR NumberW[] = {'N','u','m','b','e','r',0};
00343 
00344     hres = alloc_number(ctx, object_prototype, &number);
00345     if(FAILED(hres))
00346         return hres;
00347 
00348     V_VT(&number->num) = VT_I4;
00349     hres = create_builtin_function(ctx, NumberConstr_value, NumberW, NULL,
00350             PROPF_CONSTR|1, &number->dispex, ret);
00351 
00352     jsdisp_release(&number->dispex);
00353     return hres;
00354 }
00355 
00356 HRESULT create_number(script_ctx_t *ctx, VARIANT *num, DispatchEx **ret)
00357 {
00358     NumberInstance *number;
00359     HRESULT hres;
00360 
00361     hres = alloc_number(ctx, NULL, &number);
00362     if(FAILED(hres))
00363         return hres;
00364 
00365     number->num = *num;
00366 
00367     *ret = &number->dispex;
00368     return S_OK;
00369 }

Generated on Sun May 27 2012 04:24:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.