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

string.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 "jscript.h"
00020 
00021 #include "wine/debug.h"
00022 
00023 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
00024 
00025 typedef struct {
00026     DispatchEx dispex;
00027 
00028     WCHAR *str;
00029     DWORD length;
00030 } StringInstance;
00031 
00032 static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
00033 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
00034 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
00035 static const WCHAR anchorW[] = {'a','n','c','h','o','r',0};
00036 static const WCHAR bigW[] = {'b','i','g',0};
00037 static const WCHAR blinkW[] = {'b','l','i','n','k',0};
00038 static const WCHAR boldW[] = {'b','o','l','d',0};
00039 static const WCHAR charAtW[] = {'c','h','a','r','A','t',0};
00040 static const WCHAR charCodeAtW[] = {'c','h','a','r','C','o','d','e','A','t',0};
00041 static const WCHAR concatW[] = {'c','o','n','c','a','t',0};
00042 static const WCHAR fixedW[] = {'f','i','x','e','d',0};
00043 static const WCHAR fontcolorW[] = {'f','o','n','t','c','o','l','o','r',0};
00044 static const WCHAR fontsizeW[] = {'f','o','n','t','s','i','z','e',0};
00045 static const WCHAR indexOfW[] = {'i','n','d','e','x','O','f',0};
00046 static const WCHAR italicsW[] = {'i','t','a','l','i','c','s',0};
00047 static const WCHAR lastIndexOfW[] = {'l','a','s','t','I','n','d','e','x','O','f',0};
00048 static const WCHAR linkW[] = {'l','i','n','k',0};
00049 static const WCHAR matchW[] = {'m','a','t','c','h',0};
00050 static const WCHAR replaceW[] = {'r','e','p','l','a','c','e',0};
00051 static const WCHAR searchW[] = {'s','e','a','r','c','h',0};
00052 static const WCHAR sliceW[] = {'s','l','i','c','e',0};
00053 static const WCHAR smallW[] = {'s','m','a','l','l',0};
00054 static const WCHAR splitW[] = {'s','p','l','i','t',0};
00055 static const WCHAR strikeW[] = {'s','t','r','i','k','e',0};
00056 static const WCHAR subW[] = {'s','u','b',0};
00057 static const WCHAR substringW[] = {'s','u','b','s','t','r','i','n','g',0};
00058 static const WCHAR substrW[] = {'s','u','b','s','t','r',0};
00059 static const WCHAR supW[] = {'s','u','p',0};
00060 static const WCHAR toLowerCaseW[] = {'t','o','L','o','w','e','r','C','a','s','e',0};
00061 static const WCHAR toUpperCaseW[] = {'t','o','U','p','p','e','r','C','a','s','e',0};
00062 static const WCHAR toLocaleLowerCaseW[] = {'t','o','L','o','c','a','l','e','L','o','w','e','r','C','a','s','e',0};
00063 static const WCHAR toLocaleUpperCaseW[] = {'t','o','L','o','c','a','l','e','U','p','p','e','r','C','a','s','e',0};
00064 static const WCHAR localeCompareW[] = {'l','o','c','a','l','e','C','o','m','p','a','r','e',0};
00065 static const WCHAR fromCharCodeW[] = {'f','r','o','m','C','h','a','r','C','o','d','e',0};
00066 
00067 static inline StringInstance *string_from_vdisp(vdisp_t *vdisp)
00068 {
00069     return (StringInstance*)vdisp->u.jsdisp;
00070 }
00071 
00072 static inline StringInstance *string_this(vdisp_t *jsthis)
00073 {
00074     return is_vclass(jsthis, JSCLASS_STRING) ? string_from_vdisp(jsthis) : NULL;
00075 }
00076 
00077 static HRESULT get_string_val(script_ctx_t *ctx, vdisp_t *jsthis, jsexcept_t *ei,
00078         const WCHAR **str, DWORD *len, BSTR *val_str)
00079 {
00080     StringInstance *string;
00081     VARIANT this_var;
00082     HRESULT hres;
00083 
00084     if((string = string_this(jsthis))) {
00085         *str = string->str;
00086         *len = string->length;
00087         *val_str = NULL;
00088         return S_OK;
00089     }
00090 
00091     V_VT(&this_var) = VT_DISPATCH;
00092     V_DISPATCH(&this_var) = jsthis->u.disp;
00093     hres = to_string(ctx, &this_var, ei, val_str);
00094     if(FAILED(hres))
00095         return hres;
00096 
00097     *str = *val_str;
00098     *len = SysStringLen(*val_str);
00099     return S_OK;
00100 }
00101 
00102 static HRESULT String_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00103         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00104 {
00105     TRACE("%p\n", jsthis);
00106 
00107     switch(flags) {
00108     case DISPATCH_PROPERTYGET: {
00109         StringInstance *string = string_from_vdisp(jsthis);
00110 
00111         V_VT(retv) = VT_I4;
00112         V_I4(retv) = string->length;
00113         break;
00114     }
00115     default:
00116         FIXME("unimplemented flags %x\n", flags);
00117         return E_NOTIMPL;
00118     }
00119 
00120     return S_OK;
00121 }
00122 
00123 static HRESULT stringobj_to_string(vdisp_t *jsthis, VARIANT *retv)
00124 {
00125     StringInstance *string;
00126 
00127     if(!(string = string_this(jsthis))) {
00128         WARN("this is not a string object\n");
00129         return E_FAIL;
00130     }
00131 
00132     if(retv) {
00133         BSTR str = SysAllocString(string->str);
00134         if(!str)
00135             return E_OUTOFMEMORY;
00136 
00137         V_VT(retv) = VT_BSTR;
00138         V_BSTR(retv) = str;
00139     }
00140     return S_OK;
00141 }
00142 
00143 /* ECMA-262 3rd Edition    15.5.4.2 */
00144 static HRESULT String_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00145         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00146 {
00147     TRACE("\n");
00148 
00149     return stringobj_to_string(jsthis, retv);
00150 }
00151 
00152 /* ECMA-262 3rd Edition    15.5.4.2 */
00153 static HRESULT String_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00154         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00155 {
00156     TRACE("\n");
00157 
00158     return stringobj_to_string(jsthis, retv);
00159 }
00160 
00161 static HRESULT do_attributeless_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00162         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp, const WCHAR *tagname)
00163 {
00164     const WCHAR *str;
00165     DWORD length;
00166     BSTR val_str = NULL;
00167     HRESULT hres;
00168 
00169     static const WCHAR tagfmt[] = {'<','%','s','>','%','s','<','/','%','s','>',0};
00170 
00171     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00172     if(FAILED(hres))
00173         return hres;
00174 
00175     if(retv) {
00176         BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname) + 5);
00177         if(!ret) {
00178             SysFreeString(val_str);
00179             return E_OUTOFMEMORY;
00180         }
00181 
00182         sprintfW(ret, tagfmt, tagname, str, tagname);
00183 
00184         V_VT(retv) = VT_BSTR;
00185         V_BSTR(retv) = ret;
00186     }
00187 
00188     SysFreeString(val_str);
00189     return S_OK;
00190 }
00191 
00192 static HRESULT do_attribute_tag_format(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
00193         DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp,
00194         const WCHAR *tagname, const WCHAR *attr)
00195 {
00196     static const WCHAR tagfmtW[]
00197         = {'<','%','s',' ','%','s','=','\"','%','s','\"','>','%','s','<','/','%','s','>',0};
00198     static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0};
00199 
00200     StringInstance *string;
00201     const WCHAR *str;
00202     DWORD length;
00203     BSTR attr_value, val_str = NULL;
00204     HRESULT hres;
00205 
00206     if(!(string = string_this(jsthis))) {
00207         VARIANT this;
00208 
00209         V_VT(&this) = VT_DISPATCH;
00210         V_DISPATCH(&this) = jsthis->u.disp;
00211 
00212         hres = to_string(ctx, &this, ei, &val_str);
00213         if(FAILED(hres))
00214             return hres;
00215 
00216         str = val_str;
00217         length = SysStringLen(val_str);
00218     }
00219     else {
00220         str = string->str;
00221         length = string->length;
00222     }
00223 
00224     if(arg_cnt(dp)) {
00225         hres = to_string(ctx, get_arg(dp, 0), ei, &attr_value);
00226         if(FAILED(hres)) {
00227             SysFreeString(val_str);
00228             return hres;
00229         }
00230     }
00231     else {
00232         attr_value = SysAllocString(undefinedW);
00233         if(!attr_value) {
00234             SysFreeString(val_str);
00235             return E_OUTOFMEMORY;
00236         }
00237     }
00238 
00239     if(retv) {
00240         BSTR ret = SysAllocStringLen(NULL, length + 2*strlenW(tagname)
00241                 + strlenW(attr) + SysStringLen(attr_value) + 9);
00242         if(!ret) {
00243             SysFreeString(attr_value);
00244             SysFreeString(val_str);
00245             return E_OUTOFMEMORY;
00246         }
00247 
00248         sprintfW(ret, tagfmtW, tagname, attr, attr_value, str, tagname);
00249 
00250         V_VT(retv) = VT_BSTR;
00251         V_BSTR(retv) = ret;
00252     }
00253 
00254     SysFreeString(attr_value);
00255     SysFreeString(val_str);
00256     return S_OK;
00257 }
00258 
00259 static HRESULT String_anchor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00260         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00261 {
00262     static const WCHAR fontW[] = {'A',0};
00263     static const WCHAR colorW[] = {'N','A','M','E',0};
00264 
00265     return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
00266 }
00267 
00268 static HRESULT String_big(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00269         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00270 {
00271     static const WCHAR bigtagW[] = {'B','I','G',0};
00272     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, bigtagW);
00273 }
00274 
00275 static HRESULT String_blink(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00276         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00277 {
00278     static const WCHAR blinktagW[] = {'B','L','I','N','K',0};
00279     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, blinktagW);
00280 }
00281 
00282 static HRESULT String_bold(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00283         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00284 {
00285     static const WCHAR boldtagW[] = {'B',0};
00286     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, boldtagW);
00287 }
00288 
00289 /* ECMA-262 3rd Edition    15.5.4.5 */
00290 static HRESULT String_charAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00291         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00292 {
00293     const WCHAR *str;
00294     DWORD length;
00295     BSTR ret, val_str;
00296     INT pos = 0;
00297     HRESULT hres;
00298 
00299     TRACE("\n");
00300 
00301     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00302     if(FAILED(hres))
00303         return hres;
00304 
00305     if(arg_cnt(dp)) {
00306         VARIANT num;
00307 
00308         hres = to_integer(ctx, get_arg(dp, 0), ei, &num);
00309         if(FAILED(hres)) {
00310             SysFreeString(val_str);
00311             return hres;
00312         }
00313 
00314         if(V_VT(&num) == VT_I4) {
00315             pos = V_I4(&num);
00316         }else {
00317             WARN("pos = %lf\n", V_R8(&num));
00318             pos = -1;
00319         }
00320     }
00321 
00322     if(!retv) {
00323         SysFreeString(val_str);
00324         return S_OK;
00325     }
00326 
00327     if(0 <= pos && pos < length)
00328         ret = SysAllocStringLen(str+pos, 1);
00329     else
00330         ret = SysAllocStringLen(NULL, 0);
00331     SysFreeString(val_str);
00332     if(!ret) {
00333         return E_OUTOFMEMORY;
00334     }
00335 
00336     V_VT(retv) = VT_BSTR;
00337     V_BSTR(retv) = ret;
00338     return S_OK;
00339 }
00340 
00341 /* ECMA-262 3rd Edition    15.5.4.5 */
00342 static HRESULT String_charCodeAt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00343         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00344 {
00345     const WCHAR *str;
00346     BSTR val_str;
00347     DWORD length, idx = 0;
00348     HRESULT hres;
00349 
00350     TRACE("\n");
00351 
00352     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00353     if(FAILED(hres))
00354         return hres;
00355 
00356     if(arg_cnt(dp) > 0) {
00357         VARIANT v;
00358 
00359         hres = to_integer(ctx, get_arg(dp, 0), ei, &v);
00360         if(FAILED(hres)) {
00361             SysFreeString(val_str);
00362             return hres;
00363         }
00364 
00365         if(V_VT(&v) != VT_I4 || V_I4(&v) < 0 || V_I4(&v) >= length) {
00366             if(retv) num_set_nan(&v);
00367             SysFreeString(val_str);
00368             return S_OK;
00369         }
00370 
00371         idx = V_I4(&v);
00372     }
00373 
00374     if(retv) {
00375         V_VT(retv) = VT_I4;
00376         V_I4(retv) = str[idx];
00377     }
00378 
00379     SysFreeString(val_str);
00380     return S_OK;
00381 }
00382 
00383 /* ECMA-262 3rd Edition    15.5.4.6 */
00384 static HRESULT String_concat(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00385         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00386 {
00387     BSTR *strs = NULL, ret = NULL;
00388     DWORD len = 0, i, l, str_cnt;
00389     VARIANT var;
00390     WCHAR *ptr;
00391     HRESULT hres;
00392 
00393     TRACE("\n");
00394 
00395     str_cnt = arg_cnt(dp)+1;
00396     strs = heap_alloc_zero(str_cnt * sizeof(BSTR));
00397     if(!strs)
00398         return E_OUTOFMEMORY;
00399 
00400     V_VT(&var) = VT_DISPATCH;
00401     V_DISPATCH(&var) = jsthis->u.disp;
00402 
00403     hres = to_string(ctx, &var, ei, strs);
00404     if(SUCCEEDED(hres)) {
00405         for(i=0; i < arg_cnt(dp); i++) {
00406             hres = to_string(ctx, get_arg(dp, i), ei, strs+i+1);
00407             if(FAILED(hres))
00408                 break;
00409         }
00410     }
00411 
00412     if(SUCCEEDED(hres)) {
00413         for(i=0; i < str_cnt; i++)
00414             len += SysStringLen(strs[i]);
00415 
00416         ptr = ret = SysAllocStringLen(NULL, len);
00417 
00418         for(i=0; i < str_cnt; i++) {
00419             l = SysStringLen(strs[i]);
00420             memcpy(ptr, strs[i], l*sizeof(WCHAR));
00421             ptr += l;
00422         }
00423     }
00424 
00425     for(i=0; i < str_cnt; i++)
00426         SysFreeString(strs[i]);
00427     heap_free(strs);
00428 
00429     if(FAILED(hres))
00430         return hres;
00431 
00432     if(retv) {
00433         V_VT(retv) = VT_BSTR;
00434         V_BSTR(retv) = ret;
00435     }else {
00436         SysFreeString(ret);
00437     }
00438     return S_OK;
00439 }
00440 
00441 static HRESULT String_fixed(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00442         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00443 {
00444     static const WCHAR fixedtagW[] = {'T','T',0};
00445     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fixedtagW);
00446 }
00447 
00448 static HRESULT String_fontcolor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00449         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00450 {
00451     static const WCHAR fontW[] = {'F','O','N','T',0};
00452     static const WCHAR colorW[] = {'C','O','L','O','R',0};
00453 
00454     return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
00455 }
00456 
00457 static HRESULT String_fontsize(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00458         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00459 {
00460     static const WCHAR fontW[] = {'F','O','N','T',0};
00461     static const WCHAR colorW[] = {'S','I','Z','E',0};
00462 
00463     return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
00464 }
00465 
00466 static HRESULT String_indexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00467         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00468 {
00469     DWORD length, pos = 0;
00470     const WCHAR *str;
00471     BSTR search_str, val_str;
00472     INT ret = -1;
00473     HRESULT hres;
00474 
00475     TRACE("\n");
00476 
00477     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00478     if(FAILED(hres))
00479         return hres;
00480 
00481     if(!arg_cnt(dp)) {
00482         if(retv) {
00483             V_VT(retv) = VT_I4;
00484             V_I4(retv) = -1;
00485         }
00486         SysFreeString(val_str);
00487         return S_OK;
00488     }
00489 
00490     hres = to_string(ctx, get_arg(dp,0), ei, &search_str);
00491     if(FAILED(hres)) {
00492         SysFreeString(val_str);
00493         return hres;
00494     }
00495 
00496     if(arg_cnt(dp) >= 2) {
00497         VARIANT ival;
00498 
00499         hres = to_integer(ctx, get_arg(dp,1), ei, &ival);
00500         if(SUCCEEDED(hres)) {
00501             if(V_VT(&ival) == VT_I4)
00502                 pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0;
00503             else
00504                 pos = V_R8(&ival) > 0.0 ? length : 0;
00505             if(pos > length)
00506                 pos = length;
00507         }
00508     }
00509 
00510     if(SUCCEEDED(hres)) {
00511         const WCHAR *ptr;
00512 
00513         ptr = strstrW(str+pos, search_str);
00514         if(ptr)
00515             ret = ptr - str;
00516         else
00517             ret = -1;
00518     }
00519 
00520     SysFreeString(search_str);
00521     SysFreeString(val_str);
00522     if(FAILED(hres))
00523         return hres;
00524 
00525     if(retv) {
00526         V_VT(retv) = VT_I4;
00527         V_I4(retv) = ret;
00528     }
00529     return S_OK;
00530 }
00531 
00532 static HRESULT String_italics(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00533         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00534 {
00535     static const WCHAR italicstagW[] = {'I',0};
00536     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, italicstagW);
00537 }
00538 
00539 /* ECMA-262 3rd Edition    15.5.4.8 */
00540 static HRESULT String_lastIndexOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00541         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00542 {
00543     BSTR search_str, val_str;
00544     DWORD length, pos, search_len;
00545     const WCHAR *str;
00546     INT ret = -1;
00547     HRESULT hres;
00548 
00549     TRACE("\n");
00550 
00551     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00552     if(FAILED(hres))
00553         return hres;
00554 
00555     if(!arg_cnt(dp)) {
00556         if(retv) {
00557             V_VT(retv) = VT_I4;
00558             V_I4(retv) = -1;
00559         }
00560         SysFreeString(val_str);
00561         return S_OK;
00562     }
00563 
00564     hres = to_string(ctx, get_arg(dp,0), ei, &search_str);
00565     if(FAILED(hres)) {
00566         SysFreeString(val_str);
00567         return hres;
00568     }
00569 
00570     search_len = SysStringLen(search_str);
00571 
00572     if(arg_cnt(dp) >= 2) {
00573         VARIANT ival;
00574 
00575         hres = to_integer(ctx, get_arg(dp,1), ei, &ival);
00576         if(SUCCEEDED(hres)) {
00577             if(V_VT(&ival) == VT_I4)
00578                 pos = V_VT(&ival) > 0 ? V_I4(&ival) : 0;
00579             else
00580                 pos = V_R8(&ival) > 0.0 ? length : 0;
00581             if(pos > length)
00582                 pos = length;
00583         }
00584     }else {
00585         pos = length;
00586     }
00587 
00588     if(SUCCEEDED(hres) && length >= search_len) {
00589         const WCHAR *ptr;
00590 
00591         for(ptr = str+min(pos, length-search_len); ptr >= str; ptr--) {
00592             if(!memcmp(ptr, search_str, search_len*sizeof(WCHAR))) {
00593                 ret = ptr-str;
00594                 break;
00595             }
00596         }
00597     }
00598 
00599     SysFreeString(search_str);
00600     SysFreeString(val_str);
00601     if(FAILED(hres))
00602         return hres;
00603 
00604     if(retv) {
00605         V_VT(retv) = VT_I4;
00606         V_I4(retv) = ret;
00607     }
00608     return S_OK;
00609 }
00610 
00611 static HRESULT String_link(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00612         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00613 {
00614     static const WCHAR fontW[] = {'A',0};
00615     static const WCHAR colorW[] = {'H','R','E','F',0};
00616 
00617     return do_attribute_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, fontW, colorW);
00618 }
00619 
00620 /* ECMA-262 3rd Edition    15.5.4.10 */
00621 static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00622         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
00623 {
00624     const WCHAR *str;
00625     DispatchEx *regexp;
00626     VARIANT *arg_var;
00627     DWORD length;
00628     BSTR val_str = NULL;
00629     HRESULT hres = S_OK;
00630 
00631     TRACE("\n");
00632 
00633     if(!arg_cnt(dp)) {
00634         if(retv) {
00635             V_VT(retv) = VT_NULL;
00636         }
00637 
00638         return S_OK;
00639     }
00640 
00641     arg_var = get_arg(dp, 0);
00642     switch(V_VT(arg_var)) {
00643     case VT_DISPATCH:
00644         regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
00645         if(regexp) {
00646             if(is_class(regexp, JSCLASS_REGEXP))
00647                 break;
00648             jsdisp_release(regexp);
00649         }
00650     default: {
00651         BSTR match_str;
00652 
00653         hres = to_string(ctx, arg_var, ei, &match_str);
00654         if(FAILED(hres))
00655             return hres;
00656 
00657         hres = create_regexp(ctx, match_str, SysStringLen(match_str), 0, &regexp);
00658         SysFreeString(match_str);
00659         if(FAILED(hres))
00660             return hres;
00661     }
00662     }
00663 
00664     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00665     if(SUCCEEDED(hres)) {
00666         if(!val_str)
00667             val_str = SysAllocStringLen(str, length);
00668         if(val_str)
00669             hres = regexp_string_match(ctx, regexp, val_str, retv, ei);
00670         else
00671             hres = E_OUTOFMEMORY;
00672     }
00673 
00674     jsdisp_release(regexp);
00675     SysFreeString(val_str);
00676     return hres;
00677 }
00678 
00679 typedef struct {
00680     WCHAR *buf;
00681     DWORD size;
00682     DWORD len;
00683 } strbuf_t;
00684 
00685 static HRESULT strbuf_append(strbuf_t *buf, const WCHAR *str, DWORD len)
00686 {
00687     if(!len)
00688         return S_OK;
00689 
00690     if(len + buf->len > buf->size) {
00691         WCHAR *new_buf;
00692         DWORD new_size;
00693 
00694         new_size = buf->size ? buf->size<<1 : 16;
00695         if(new_size < buf->len+len)
00696             new_size = buf->len+len;
00697         if(buf->buf)
00698             new_buf = heap_realloc(buf->buf, new_size*sizeof(WCHAR));
00699         else
00700             new_buf = heap_alloc(new_size*sizeof(WCHAR));
00701         if(!new_buf)
00702             return E_OUTOFMEMORY;
00703 
00704         buf->buf = new_buf;
00705         buf->size = new_size;
00706     }
00707 
00708     memcpy(buf->buf+buf->len, str, len*sizeof(WCHAR));
00709     buf->len += len;
00710     return S_OK;
00711 }
00712 
00713 static HRESULT rep_call(script_ctx_t *ctx, DispatchEx *func, const WCHAR *str, match_result_t *match,
00714         match_result_t *parens, DWORD parens_cnt, BSTR *ret, jsexcept_t *ei, IServiceProvider *caller)
00715 {
00716     DISPPARAMS dp = {NULL, NULL, 0, 0};
00717     VARIANTARG *args, *arg;
00718     VARIANT var;
00719     DWORD i;
00720     HRESULT hres = S_OK;
00721 
00722     dp.cArgs = parens_cnt+3;
00723     dp.rgvarg = args = heap_alloc_zero(sizeof(VARIANT)*dp.cArgs);
00724     if(!args)
00725         return E_OUTOFMEMORY;
00726 
00727     arg = get_arg(&dp,0);
00728     V_VT(arg) = VT_BSTR;
00729     V_BSTR(arg) = SysAllocStringLen(match->str, match->len);
00730     if(!V_BSTR(arg))
00731         hres = E_OUTOFMEMORY;
00732 
00733     if(SUCCEEDED(hres)) {
00734         for(i=0; i < parens_cnt; i++) {
00735             arg = get_arg(&dp,i+1);
00736             V_VT(arg) = VT_BSTR;
00737             V_BSTR(arg) = SysAllocStringLen(parens[i].str, parens[i].len);
00738             if(!V_BSTR(arg)) {
00739                hres = E_OUTOFMEMORY;
00740                break;
00741             }
00742         }
00743     }
00744 
00745     if(SUCCEEDED(hres)) {
00746         arg = get_arg(&dp,parens_cnt+1);
00747         V_VT(arg) = VT_I4;
00748         V_I4(arg) = match->str - str;
00749 
00750         arg = get_arg(&dp,parens_cnt+2);
00751         V_VT(arg) = VT_BSTR;
00752         V_BSTR(arg) = SysAllocString(str);
00753         if(!V_BSTR(arg))
00754             hres = E_OUTOFMEMORY;
00755     }
00756 
00757     if(SUCCEEDED(hres))
00758         hres = jsdisp_call_value(func, DISPATCH_METHOD, &dp, &var, ei, caller);
00759 
00760     for(i=0; i < parens_cnt+3; i++) {
00761         if(i != parens_cnt+1)
00762             SysFreeString(V_BSTR(get_arg(&dp,i)));
00763     }
00764     heap_free(args);
00765 
00766     if(FAILED(hres))
00767         return hres;
00768 
00769     hres = to_string(ctx, &var, ei, ret);
00770     VariantClear(&var);
00771     return hres;
00772 }
00773 
00774 /* ECMA-262 3rd Edition    15.5.4.11 */
00775 static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00776         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00777 {
00778     const WCHAR *str;
00779     DWORD parens_cnt = 0, parens_size=0, rep_len=0, length;
00780     BSTR rep_str = NULL, match_str = NULL, ret_str, val_str;
00781     DispatchEx *rep_func = NULL, *regexp = NULL;
00782     match_result_t *parens = NULL, match = {NULL,0}, **parens_ptr = &parens;
00783     strbuf_t ret = {NULL,0,0};
00784     DWORD re_flags = REM_NO_CTX_UPDATE;
00785     VARIANT *arg_var;
00786     HRESULT hres = S_OK;
00787 
00788     TRACE("\n");
00789 
00790     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
00791     if(FAILED(hres))
00792         return hres;
00793 
00794     if(!arg_cnt(dp)) {
00795         if(retv) {
00796             if(!val_str) {
00797                 val_str = SysAllocStringLen(str, length);
00798                 if(!val_str)
00799                     return E_OUTOFMEMORY;
00800             }
00801 
00802             V_VT(retv) = VT_BSTR;
00803             V_BSTR(retv) = val_str;
00804         }
00805         return S_OK;
00806     }
00807 
00808     arg_var = get_arg(dp, 0);
00809     switch(V_VT(arg_var)) {
00810     case VT_DISPATCH:
00811         regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
00812         if(regexp) {
00813             if(is_class(regexp, JSCLASS_REGEXP)) {
00814                 break;
00815             }else {
00816                 jsdisp_release(regexp);
00817                 regexp = NULL;
00818             }
00819         }
00820 
00821     default:
00822         hres = to_string(ctx, arg_var, ei, &match_str);
00823         if(FAILED(hres)) {
00824             SysFreeString(val_str);
00825             return hres;
00826         }
00827     }
00828 
00829     if(arg_cnt(dp) >= 2) {
00830         arg_var = get_arg(dp,1);
00831         switch(V_VT(arg_var)) {
00832         case VT_DISPATCH:
00833             rep_func = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg_var));
00834             if(rep_func) {
00835                 if(is_class(rep_func, JSCLASS_FUNCTION)) {
00836                     break;
00837                 }else {
00838                     jsdisp_release(rep_func);
00839                     rep_func = NULL;
00840                 }
00841             }
00842 
00843         default:
00844             hres = to_string(ctx, arg_var, ei, &rep_str);
00845             if(FAILED(hres))
00846                 break;
00847 
00848             rep_len = SysStringLen(rep_str);
00849             if(!strchrW(rep_str, '$'))
00850                 parens_ptr = NULL;
00851         }
00852     }
00853 
00854     if(SUCCEEDED(hres)) {
00855         const WCHAR *cp, *ecp;
00856 
00857         cp = ecp = str;
00858 
00859         while(1) {
00860             if(regexp) {
00861                 hres = regexp_match_next(ctx, regexp, re_flags, str, length, &cp, parens_ptr,
00862                         &parens_size, &parens_cnt, &match);
00863                 re_flags |= REM_CHECK_GLOBAL;
00864 
00865                 if(hres == S_FALSE) {
00866                     hres = S_OK;
00867                     break;
00868                 }
00869                 if(FAILED(hres))
00870                     break;
00871             }else {
00872                 match.str = strstrW(cp, match_str);
00873                 if(!match.str)
00874                     break;
00875                 match.len = SysStringLen(match_str);
00876                 cp = match.str+match.len;
00877             }
00878 
00879             hres = strbuf_append(&ret, ecp, match.str-ecp);
00880             ecp = match.str+match.len;
00881             if(FAILED(hres))
00882                 break;
00883 
00884             if(rep_func) {
00885                 BSTR cstr;
00886 
00887                 hres = rep_call(ctx, rep_func, str, &match, parens, parens_cnt, &cstr, ei, caller);
00888                 if(FAILED(hres))
00889                     break;
00890 
00891                 hres = strbuf_append(&ret, cstr, SysStringLen(cstr));
00892                 SysFreeString(cstr);
00893                 if(FAILED(hres))
00894                     break;
00895             }else if(rep_str && regexp) {
00896                 const WCHAR *ptr = rep_str, *ptr2;
00897 
00898                 while((ptr2 = strchrW(ptr, '$'))) {
00899                     hres = strbuf_append(&ret, ptr, ptr2-ptr);
00900                     if(FAILED(hres))
00901                         break;
00902 
00903                     switch(ptr2[1]) {
00904                     case '$':
00905                         hres = strbuf_append(&ret, ptr2, 1);
00906                         ptr = ptr2+2;
00907                         break;
00908                     case '&':
00909                         hres = strbuf_append(&ret, match.str, match.len);
00910                         ptr = ptr2+2;
00911                         break;
00912                     case '`':
00913                         hres = strbuf_append(&ret, str, match.str-str);
00914                         ptr = ptr2+2;
00915                         break;
00916                     case '\'':
00917                         hres = strbuf_append(&ret, ecp, (str+length)-ecp);
00918                         ptr = ptr2+2;
00919                         break;
00920                     default: {
00921                         DWORD idx;
00922 
00923                         if(!isdigitW(ptr2[1])) {
00924                             hres = strbuf_append(&ret, ptr2, 1);
00925                             ptr = ptr2+1;
00926                             break;
00927                         }
00928 
00929                         idx = ptr2[1] - '0';
00930                         if(isdigitW(ptr2[2]) && idx*10 + (ptr2[2]-'0') <= parens_cnt) {
00931                             idx = idx*10 + (ptr[2]-'0');
00932                             ptr = ptr2+3;
00933                         }else if(idx && idx <= parens_cnt) {
00934                             ptr = ptr2+2;
00935                         }else {
00936                             hres = strbuf_append(&ret, ptr2, 1);
00937                             ptr = ptr2+1;
00938                             break;
00939                         }
00940 
00941                         hres = strbuf_append(&ret, parens[idx-1].str, parens[idx-1].len);
00942                     }
00943                     }
00944 
00945                     if(FAILED(hres))
00946                         break;
00947                 }
00948 
00949                 if(SUCCEEDED(hres))
00950                     hres = strbuf_append(&ret, ptr, (rep_str+rep_len)-ptr);
00951                 if(FAILED(hres))
00952                     break;
00953             }else if(rep_str) {
00954                 hres = strbuf_append(&ret, rep_str, rep_len);
00955                 if(FAILED(hres))
00956                     break;
00957             }else {
00958                 static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d'};
00959 
00960                 hres = strbuf_append(&ret, undefinedW, sizeof(undefinedW)/sizeof(WCHAR));
00961                 if(FAILED(hres))
00962                     break;
00963             }
00964         }
00965 
00966         if(SUCCEEDED(hres))
00967             hres = strbuf_append(&ret, ecp, (str+length)-ecp);
00968     }
00969 
00970     if(rep_func)
00971         jsdisp_release(rep_func);
00972     SysFreeString(rep_str);
00973     SysFreeString(match_str);
00974     heap_free(parens);
00975 
00976     if(SUCCEEDED(hres) && match.str && regexp) {
00977         if(!val_str)
00978             val_str = SysAllocStringLen(str, length);
00979         if(val_str) {
00980             SysFreeString(ctx->last_match);
00981             ctx->last_match = val_str;
00982             val_str = NULL;
00983             ctx->last_match_index = match.str-str;
00984             ctx->last_match_length = match.len;
00985         }else {
00986             hres = E_OUTOFMEMORY;
00987         }
00988     }
00989 
00990     if(regexp)
00991         jsdisp_release(regexp);
00992     SysFreeString(val_str);
00993 
00994     if(SUCCEEDED(hres) && retv) {
00995         ret_str = SysAllocStringLen(ret.buf, ret.len);
00996         if(!ret_str)
00997             return E_OUTOFMEMORY;
00998 
00999         V_VT(retv) = VT_BSTR;
01000         V_BSTR(retv) = ret_str;
01001         TRACE("= %s\n", debugstr_w(ret_str));
01002     }
01003 
01004     heap_free(ret.buf);
01005     return hres;
01006 }
01007 
01008 static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01009         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01010 {
01011     DispatchEx *regexp = NULL;
01012     const WCHAR *str, *cp;
01013     match_result_t match;
01014     VARIANT *arg;
01015     DWORD length;
01016     BSTR val_str;
01017     HRESULT hres;
01018 
01019     TRACE("\n");
01020 
01021     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01022     if(FAILED(hres))
01023         return hres;
01024 
01025     if(!arg_cnt(dp)) {
01026         if(retv)
01027             V_VT(retv) = VT_NULL;
01028         SysFreeString(val_str);
01029         return S_OK;
01030     }
01031 
01032     arg = get_arg(dp,0);
01033     if(V_VT(arg) == VT_DISPATCH) {
01034         regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
01035         if(regexp) {
01036             if(!is_class(regexp, JSCLASS_REGEXP)) {
01037                 jsdisp_release(regexp);
01038                 regexp = NULL;
01039             }
01040         }
01041     }
01042 
01043     if(!regexp) {
01044         hres = create_regexp_var(ctx, arg, NULL, &regexp);
01045         if(FAILED(hres)) {
01046             SysFreeString(val_str);
01047             return hres;
01048         }
01049     }
01050 
01051     cp = str;
01052     hres = regexp_match_next(ctx, regexp, REM_RESET_INDEX, str, length, &cp, NULL, NULL, NULL, &match);
01053     SysFreeString(val_str);
01054     jsdisp_release(regexp);
01055     if(FAILED(hres))
01056         return hres;
01057 
01058     if(retv) {
01059         V_VT(retv) = VT_I4;
01060         V_I4(retv) = hres == S_OK ? match.str-str : -1;
01061     }
01062     return S_OK;
01063 }
01064 
01065 /* ECMA-262 3rd Edition    15.5.4.13 */
01066 static HRESULT String_slice(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01067         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01068 {
01069     const WCHAR *str;
01070     BSTR val_str;
01071     DWORD length;
01072     INT start=0, end;
01073     VARIANT v;
01074     HRESULT hres;
01075 
01076     TRACE("\n");
01077 
01078     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01079     if(FAILED(hres))
01080         return hres;
01081 
01082     if(arg_cnt(dp)) {
01083         hres = to_integer(ctx, get_arg(dp,0), ei, &v);
01084         if(FAILED(hres)) {
01085             SysFreeString(val_str);
01086             return hres;
01087         }
01088 
01089         if(V_VT(&v) == VT_I4) {
01090             start = V_I4(&v);
01091             if(start < 0) {
01092                 start = length + start;
01093                 if(start < 0)
01094                     start = 0;
01095             }else if(start > length) {
01096                 start = length;
01097             }
01098         }else {
01099             start = V_R8(&v) < 0.0 ? 0 : length;
01100         }
01101     }else {
01102         start = 0;
01103     }
01104 
01105     if(arg_cnt(dp) >= 2) {
01106         hres = to_integer(ctx, get_arg(dp,1), ei, &v);
01107         if(FAILED(hres)) {
01108             SysFreeString(val_str);
01109             return hres;
01110         }
01111 
01112         if(V_VT(&v) == VT_I4) {
01113             end = V_I4(&v);
01114             if(end < 0) {
01115                 end = length + end;
01116                 if(end < 0)
01117                     end = 0;
01118             }else if(end > length) {
01119                 end = length;
01120             }
01121         }else {
01122             end = V_R8(&v) < 0.0 ? 0 : length;
01123         }
01124     }else {
01125         end = length;
01126     }
01127 
01128     if(end < start)
01129         end = start;
01130 
01131     if(retv) {
01132         BSTR retstr = SysAllocStringLen(str+start, end-start);
01133         if(!retstr) {
01134             SysFreeString(val_str);
01135             return E_OUTOFMEMORY;
01136         }
01137 
01138         V_VT(retv) = VT_BSTR;
01139         V_BSTR(retv) = retstr;
01140     }
01141 
01142     SysFreeString(val_str);
01143     return S_OK;
01144 }
01145 
01146 static HRESULT String_small(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01147         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01148 {
01149     static const WCHAR smalltagW[] = {'S','M','A','L','L',0};
01150     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, smalltagW);
01151 }
01152 
01153 static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01154         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01155 {
01156     match_result_t *match_result = NULL;
01157     DWORD length, match_cnt, i, match_len = 0;
01158     const WCHAR *str, *ptr, *ptr2;
01159     BOOL use_regexp = FALSE;
01160     VARIANT *arg, var;
01161     DispatchEx *array;
01162     BSTR val_str, match_str = NULL;
01163     HRESULT hres;
01164 
01165     TRACE("\n");
01166 
01167     if(arg_cnt(dp) != 1) {
01168         FIXME("unsupported args\n");
01169         return E_NOTIMPL;
01170     }
01171 
01172     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01173     if(FAILED(hres))
01174         return hres;
01175 
01176     arg = get_arg(dp, 0);
01177     switch(V_VT(arg)) {
01178     case VT_DISPATCH: {
01179         DispatchEx *regexp;
01180 
01181         regexp = iface_to_jsdisp((IUnknown*)V_DISPATCH(arg));
01182         if(regexp) {
01183             if(is_class(regexp, JSCLASS_REGEXP)) {
01184                 use_regexp = TRUE;
01185                 hres = regexp_match(ctx, regexp, str, length, TRUE, &match_result, &match_cnt);
01186                 jsdisp_release(regexp);
01187                 if(FAILED(hres)) {
01188                     SysFreeString(val_str);
01189                     return hres;
01190                 }
01191                 break;
01192             }
01193             jsdisp_release(regexp);
01194         }
01195     }
01196     default:
01197         hres = to_string(ctx, arg, ei, &match_str);
01198         if(FAILED(hres)) {
01199             SysFreeString(val_str);
01200             return hres;
01201         }
01202 
01203         match_len = SysStringLen(match_str);
01204         if(!match_len) {
01205             SysFreeString(match_str);
01206             match_str = NULL;
01207         }
01208     }
01209 
01210     hres = create_array(ctx, 0, &array);
01211 
01212     if(SUCCEEDED(hres)) {
01213         ptr = str;
01214         for(i=0;; i++) {
01215             if(use_regexp) {
01216                 if(i == match_cnt)
01217                     break;
01218                 ptr2 = match_result[i].str;
01219             }else if(match_str) {
01220                 ptr2 = strstrW(ptr, match_str);
01221                 if(!ptr2)
01222                     break;
01223             }else {
01224                 if(!*ptr)
01225                     break;
01226                 ptr2 = ptr+1;
01227             }
01228 
01229             V_VT(&var) = VT_BSTR;
01230             V_BSTR(&var) = SysAllocStringLen(ptr, ptr2-ptr);
01231             if(!V_BSTR(&var)) {
01232                 hres = E_OUTOFMEMORY;
01233                 break;
01234             }
01235 
01236             hres = jsdisp_propput_idx(array, i, &var, ei, sp);
01237             SysFreeString(V_BSTR(&var));
01238             if(FAILED(hres))
01239                 break;
01240 
01241             if(use_regexp)
01242                 ptr = match_result[i].str + match_result[i].len;
01243             else if(match_str)
01244                 ptr = ptr2 + match_len;
01245             else
01246                 ptr++;
01247         }
01248     }
01249 
01250     if(SUCCEEDED(hres) && (match_str || use_regexp)) {
01251         DWORD len = (str+length) - ptr;
01252 
01253         if(len || match_str) {
01254             V_VT(&var) = VT_BSTR;
01255             V_BSTR(&var) = SysAllocStringLen(ptr, len);
01256 
01257             if(V_BSTR(&var)) {
01258                 hres = jsdisp_propput_idx(array, i, &var, ei, sp);
01259                 SysFreeString(V_BSTR(&var));
01260             }else {
01261                 hres = E_OUTOFMEMORY;
01262             }
01263         }
01264     }
01265 
01266     SysFreeString(match_str);
01267     SysFreeString(val_str);
01268     heap_free(match_result);
01269 
01270     if(SUCCEEDED(hres) && retv) {
01271         V_VT(retv) = VT_DISPATCH;
01272         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(array);
01273     }else {
01274         jsdisp_release(array);
01275     }
01276 
01277     return hres;
01278 }
01279 
01280 static HRESULT String_strike(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01281         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01282 {
01283     static const WCHAR striketagW[] = {'S','T','R','I','K','E',0};
01284     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, striketagW);
01285 }
01286 
01287 static HRESULT String_sub(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01288         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01289 {
01290     static const WCHAR subtagW[] = {'S','U','B',0};
01291     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, subtagW);
01292 }
01293 
01294 /* ECMA-262 3rd Edition    15.5.4.15 */
01295 static HRESULT String_substring(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01296         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01297 {
01298     const WCHAR *str;
01299     BSTR val_str;
01300     INT start=0, end;
01301     DWORD length;
01302     VARIANT v;
01303     HRESULT hres;
01304 
01305     TRACE("\n");
01306 
01307     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01308     if(FAILED(hres))
01309         return hres;
01310 
01311     if(arg_cnt(dp) >= 1) {
01312         hres = to_integer(ctx, get_arg(dp,0), ei, &v);
01313         if(FAILED(hres)) {
01314             SysFreeString(val_str);
01315             return hres;
01316         }
01317 
01318         if(V_VT(&v) == VT_I4) {
01319             start = V_I4(&v);
01320             if(start < 0)
01321                 start = 0;
01322             else if(start >= length)
01323                 start = length;
01324         }else {
01325             start = V_R8(&v) < 0.0 ? 0 : length;
01326         }
01327     }
01328 
01329     if(arg_cnt(dp) >= 2) {
01330         hres = to_integer(ctx, get_arg(dp,1), ei, &v);
01331         if(FAILED(hres)) {
01332             SysFreeString(val_str);
01333             return hres;
01334         }
01335 
01336         if(V_VT(&v) == VT_I4) {
01337             end = V_I4(&v);
01338             if(end < 0)
01339                 end = 0;
01340             else if(end > length)
01341                 end = length;
01342         }else {
01343             end = V_R8(&v) < 0.0 ? 0 : length;
01344         }
01345     }else {
01346         end = length;
01347     }
01348 
01349     if(start > end) {
01350         INT tmp = start;
01351         start = end;
01352         end = tmp;
01353     }
01354 
01355     if(retv) {
01356         V_VT(retv) = VT_BSTR;
01357         V_BSTR(retv) = SysAllocStringLen(str+start, end-start);
01358         if(!V_BSTR(retv)) {
01359             SysFreeString(val_str);
01360             return E_OUTOFMEMORY;
01361         }
01362     }
01363     SysFreeString(val_str);
01364     return S_OK;
01365 }
01366 
01367 /* ECMA-262 3rd Edition    B.2.3 */
01368 static HRESULT String_substr(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01369         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01370 {
01371     BSTR val_str;
01372     const WCHAR *str;
01373     INT start=0, len;
01374     DWORD length;
01375     VARIANT v;
01376     HRESULT hres;
01377 
01378     TRACE("\n");
01379 
01380     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01381     if(FAILED(hres))
01382         return hres;
01383 
01384     if(arg_cnt(dp) >= 1) {
01385         hres = to_integer(ctx, get_arg(dp,0), ei, &v);
01386         if(FAILED(hres)) {
01387             SysFreeString(val_str);
01388             return hres;
01389         }
01390 
01391         if(V_VT(&v) == VT_I4) {
01392             start = V_I4(&v);
01393             if(start < 0)
01394                 start = 0;
01395             else if(start >= length)
01396                 start = length;
01397         }else {
01398             start = V_R8(&v) < 0.0 ? 0 : length;
01399         }
01400     }
01401 
01402     if(arg_cnt(dp) >= 2) {
01403         hres = to_integer(ctx, get_arg(dp,1), ei, &v);
01404         if(FAILED(hres)) {
01405             SysFreeString(val_str);
01406             return hres;
01407         }
01408 
01409         if(V_VT(&v) == VT_I4) {
01410             len = V_I4(&v);
01411             if(len < 0)
01412                 len = 0;
01413             else if(len > length-start)
01414                 len = length-start;
01415         }else {
01416             len = V_R8(&v) < 0.0 ? 0 : length-start;
01417         }
01418     }else {
01419         len = length-start;
01420     }
01421 
01422     hres = S_OK;
01423     if(retv) {
01424         V_VT(retv) = VT_BSTR;
01425         V_BSTR(retv) = SysAllocStringLen(str+start, len);
01426         if(!V_BSTR(retv))
01427             hres = E_OUTOFMEMORY;
01428     }
01429 
01430     SysFreeString(val_str);
01431     return hres;
01432 }
01433 
01434 static HRESULT String_sup(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01435         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01436 {
01437     static const WCHAR suptagW[] = {'S','U','P',0};
01438     return do_attributeless_tag_format(ctx, jsthis, flags, dp, retv, ei, sp, suptagW);
01439 }
01440 
01441 static HRESULT String_toLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01442         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01443 {
01444     const WCHAR* str;
01445     DWORD length;
01446     BSTR val_str;
01447     HRESULT  hres;
01448 
01449     TRACE("\n");
01450 
01451     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01452     if(FAILED(hres))
01453         return hres;
01454 
01455     if(retv) {
01456         if(!val_str) {
01457             val_str = SysAllocStringLen(str, length);
01458             if(!val_str)
01459                 return E_OUTOFMEMORY;
01460         }
01461 
01462         strlwrW(val_str);
01463 
01464         V_VT(retv) = VT_BSTR;
01465         V_BSTR(retv) = val_str;
01466     }
01467     else SysFreeString(val_str);
01468     return S_OK;
01469 }
01470 
01471 static HRESULT String_toUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01472         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01473 {
01474     const WCHAR* str;
01475     DWORD length;
01476     BSTR val_str;
01477     HRESULT hres;
01478 
01479     TRACE("\n");
01480 
01481     hres = get_string_val(ctx, jsthis, ei, &str, &length, &val_str);
01482     if(FAILED(hres))
01483         return hres;
01484 
01485     if(retv) {
01486         if(!val_str) {
01487             val_str = SysAllocStringLen(str, length);
01488             if(!val_str)
01489                 return E_OUTOFMEMORY;
01490         }
01491 
01492         struprW(val_str);
01493 
01494         V_VT(retv) = VT_BSTR;
01495         V_BSTR(retv) = val_str;
01496     }
01497     else SysFreeString(val_str);
01498     return S_OK;
01499 }
01500 
01501 static HRESULT String_toLocaleLowerCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01502         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01503 {
01504     FIXME("\n");
01505     return E_NOTIMPL;
01506 }
01507 
01508 static HRESULT String_toLocaleUpperCase(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01509         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01510 {
01511     FIXME("\n");
01512     return E_NOTIMPL;
01513 }
01514 
01515 static HRESULT String_localeCompare(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01516         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01517 {
01518     FIXME("\n");
01519     return E_NOTIMPL;
01520 }
01521 
01522 static HRESULT String_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01523         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01524 {
01525     StringInstance *This = string_from_vdisp(jsthis);
01526 
01527     TRACE("\n");
01528 
01529     switch(flags) {
01530     case INVOKE_FUNC:
01531         return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
01532     case DISPATCH_PROPERTYGET: {
01533         BSTR str = SysAllocString(This->str);
01534         if(!str)
01535             return E_OUTOFMEMORY;
01536 
01537         V_VT(retv) = VT_BSTR;
01538         V_BSTR(retv) = str;
01539         break;
01540     }
01541     default:
01542         FIXME("flags %x\n", flags);
01543         return E_NOTIMPL;
01544     }
01545 
01546     return S_OK;
01547 }
01548 
01549 static void String_destructor(DispatchEx *dispex)
01550 {
01551     StringInstance *This = (StringInstance*)dispex;
01552 
01553     heap_free(This->str);
01554     heap_free(This);
01555 }
01556 
01557 static const builtin_prop_t String_props[] = {
01558     {anchorW,                String_anchor,                PROPF_METHOD|1},
01559     {bigW,                   String_big,                   PROPF_METHOD},
01560     {blinkW,                 String_blink,                 PROPF_METHOD},
01561     {boldW,                  String_bold,                  PROPF_METHOD},
01562     {charAtW,                String_charAt,                PROPF_METHOD|1},
01563     {charCodeAtW,            String_charCodeAt,            PROPF_METHOD|1},
01564     {concatW,                String_concat,                PROPF_METHOD|1},
01565     {fixedW,                 String_fixed,                 PROPF_METHOD},
01566     {fontcolorW,             String_fontcolor,             PROPF_METHOD|1},
01567     {fontsizeW,              String_fontsize,              PROPF_METHOD|1},
01568     {indexOfW,               String_indexOf,               PROPF_METHOD|2},
01569     {italicsW,               String_italics,               PROPF_METHOD},
01570     {lastIndexOfW,           String_lastIndexOf,           PROPF_METHOD|2},
01571     {lengthW,                String_length,                0},
01572     {linkW,                  String_link,                  PROPF_METHOD|1},
01573     {localeCompareW,         String_localeCompare,         PROPF_METHOD|1},
01574     {matchW,                 String_match,                 PROPF_METHOD|1},
01575     {replaceW,               String_replace,               PROPF_METHOD|1},
01576     {searchW,                String_search,                PROPF_METHOD},
01577     {sliceW,                 String_slice,                 PROPF_METHOD},
01578     {smallW,                 String_small,                 PROPF_METHOD},
01579     {splitW,                 String_split,                 PROPF_METHOD|2},
01580     {strikeW,                String_strike,                PROPF_METHOD},
01581     {subW,                   String_sub,                   PROPF_METHOD},
01582     {substrW,                String_substr,                PROPF_METHOD|2},
01583     {substringW,             String_substring,             PROPF_METHOD|2},
01584     {supW,                   String_sup,                   PROPF_METHOD},
01585     {toLocaleLowerCaseW,     String_toLocaleLowerCase,     PROPF_METHOD},
01586     {toLocaleUpperCaseW,     String_toLocaleUpperCase,     PROPF_METHOD},
01587     {toLowerCaseW,           String_toLowerCase,           PROPF_METHOD},
01588     {toStringW,              String_toString,              PROPF_METHOD},
01589     {toUpperCaseW,           String_toUpperCase,           PROPF_METHOD},
01590     {valueOfW,               String_valueOf,               PROPF_METHOD}
01591 };
01592 
01593 static const builtin_info_t String_info = {
01594     JSCLASS_STRING,
01595     {NULL, String_value, 0},
01596     sizeof(String_props)/sizeof(*String_props),
01597     String_props,
01598     String_destructor,
01599     NULL
01600 };
01601 
01602 /* ECMA-262 3rd Edition    15.5.3.2 */
01603 static HRESULT StringConstr_fromCharCode(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
01604         DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01605 {
01606     DWORD i, code;
01607     BSTR ret;
01608     HRESULT hres;
01609 
01610     ret = SysAllocStringLen(NULL, arg_cnt(dp));
01611     if(!ret)
01612         return E_OUTOFMEMORY;
01613 
01614     for(i=0; i<arg_cnt(dp); i++) {
01615         hres = to_uint32(ctx, get_arg(dp, i), ei, &code);
01616         if(FAILED(hres)) {
01617             SysFreeString(ret);
01618             return hres;
01619         }
01620 
01621         ret[i] = code;
01622     }
01623 
01624     if(retv) {
01625         V_VT(retv) = VT_BSTR;
01626         V_BSTR(retv) = ret;
01627     }
01628     else SysFreeString(ret);
01629 
01630     return S_OK;
01631 }
01632 
01633 static HRESULT StringConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01634         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
01635 {
01636     HRESULT hres;
01637 
01638     TRACE("\n");
01639 
01640     switch(flags) {
01641     case INVOKE_FUNC: {
01642         BSTR str;
01643 
01644         if(arg_cnt(dp)) {
01645             hres = to_string(ctx, get_arg(dp, 0), ei, &str);
01646             if(FAILED(hres))
01647                 return hres;
01648         }else {
01649             str = SysAllocStringLen(NULL, 0);
01650             if(!str)
01651                 return E_OUTOFMEMORY;
01652         }
01653 
01654         V_VT(retv) = VT_BSTR;
01655         V_BSTR(retv) = str;
01656         break;
01657     }
01658     case DISPATCH_CONSTRUCT: {
01659         DispatchEx *ret;
01660 
01661         if(arg_cnt(dp)) {
01662             BSTR str;
01663 
01664             hres = to_string(ctx, get_arg(dp, 0), ei, &str);
01665             if(FAILED(hres))
01666                 return hres;
01667 
01668             hres = create_string(ctx, str, SysStringLen(str), &ret);
01669             SysFreeString(str);
01670         }else {
01671             hres = create_string(ctx, NULL, 0, &ret);
01672         }
01673 
01674         if(FAILED(hres))
01675             return hres;
01676 
01677         V_VT(retv) = VT_DISPATCH;
01678         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(ret);
01679         break;
01680     }
01681 
01682     default:
01683         FIXME("unimplemented flags: %x\n", flags);
01684         return E_NOTIMPL;
01685     }
01686 
01687     return S_OK;
01688 }
01689 
01690 static HRESULT string_alloc(script_ctx_t *ctx, DispatchEx *object_prototype, StringInstance **ret)
01691 {
01692     StringInstance *string;
01693     HRESULT hres;
01694 
01695     string = heap_alloc_zero(sizeof(StringInstance));
01696     if(!string)
01697         return E_OUTOFMEMORY;
01698 
01699     if(object_prototype)
01700         hres = init_dispex(&string->dispex, ctx, &String_info, object_prototype);
01701     else
01702         hres = init_dispex_from_constr(&string->dispex, ctx, &String_info, ctx->string_constr);
01703     if(FAILED(hres)) {
01704         heap_free(string);
01705         return hres;
01706     }
01707 
01708     *ret = string;
01709     return S_OK;
01710 }
01711 
01712 static const builtin_prop_t StringConstr_props[] = {
01713     {fromCharCodeW,    StringConstr_fromCharCode,    PROPF_METHOD},
01714 };
01715 
01716 static const builtin_info_t StringConstr_info = {
01717     JSCLASS_FUNCTION,
01718     {NULL, Function_value, 0},
01719     sizeof(StringConstr_props)/sizeof(*StringConstr_props),
01720     StringConstr_props,
01721     NULL,
01722     NULL
01723 };
01724 
01725 HRESULT create_string_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
01726 {
01727     StringInstance *string;
01728     HRESULT hres;
01729 
01730     static const WCHAR StringW[] = {'S','t','r','i','n','g',0};
01731 
01732     hres = string_alloc(ctx, object_prototype, &string);
01733     if(FAILED(hres))
01734         return hres;
01735 
01736     hres = create_builtin_function(ctx, StringConstr_value, StringW, &StringConstr_info,
01737             PROPF_CONSTR|1, &string->dispex, ret);
01738 
01739     jsdisp_release(&string->dispex);
01740     return hres;
01741 }
01742 
01743 HRESULT create_string(script_ctx_t *ctx, const WCHAR *str, DWORD len, DispatchEx **ret)
01744 {
01745     StringInstance *string;
01746     HRESULT hres;
01747 
01748     hres = string_alloc(ctx, NULL, &string);
01749     if(FAILED(hres))
01750         return hres;
01751 
01752     if(len == -1)
01753         len = strlenW(str);
01754 
01755     string->length = len;
01756     string->str = heap_alloc((len+1)*sizeof(WCHAR));
01757     if(!string->str) {
01758         jsdisp_release(&string->dispex);
01759         return E_OUTOFMEMORY;
01760     }
01761 
01762     memcpy(string->str, str, len*sizeof(WCHAR));
01763     string->str[len] = 0;
01764 
01765     *ret = &string->dispex;
01766     return S_OK;
01767 
01768 }

Generated on Sun May 27 2012 04:17:49 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.