Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstring.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, ®exp); 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, ®exp); 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
1.7.6.1
|