📄 jsstr.c
字号:
thatStr = js_ValueToString(cx, argv[0]); if (!thatStr) return JS_FALSE; if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) { argv[0] = STRING_TO_JSVAL(thatStr); return cx->localeCallbacks->localeCompare(cx, str, thatStr, rval); } *rval = INT_TO_JSVAL(js_CompareStrings(str, thatStr)); } return JS_TRUE;}static JSBoolstr_charAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSString *str; jsdouble d; size_t index; str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); if (!str) return JS_FALSE; argv[-1] = STRING_TO_JSVAL(str); if (argc == 0) { d = 0.0; } else { if (!js_ValueToNumber(cx, argv[0], &d)) return JS_FALSE; d = js_DoubleToInteger(d); } if (d < 0 || JSSTRING_LENGTH(str) <= d) { *rval = JS_GetEmptyStringValue(cx); } else { index = (size_t)d; str = js_NewDependentString(cx, str, index, 1, 0); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); } return JS_TRUE;}static JSBoolstr_charCodeAt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSString *str; jsdouble d; size_t index; str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); if (!str) return JS_FALSE; argv[-1] = STRING_TO_JSVAL(str); if (argc == 0) { d = 0.0; } else { if (!js_ValueToNumber(cx, argv[0], &d)) return JS_FALSE; d = js_DoubleToInteger(d); } if (d < 0 || JSSTRING_LENGTH(str) <= d) { *rval = JS_GetNaNValue(cx); } else { index = (size_t)d; *rval = INT_TO_JSVAL((jsint) JSSTRING_CHARS(str)[index]); } return JS_TRUE;}jsintjs_BoyerMooreHorspool(const jschar *text, jsint textlen, const jschar *pat, jsint patlen, jsint start){ jsint i, j, k, m; uint8 skip[BMH_CHARSET_SIZE]; jschar c; JS_ASSERT(0 < patlen && patlen <= BMH_PATLEN_MAX); for (i = 0; i < BMH_CHARSET_SIZE; i++) skip[i] = (uint8)patlen; m = patlen - 1; for (i = 0; i < m; i++) { c = pat[i]; if (c >= BMH_CHARSET_SIZE) return BMH_BAD_PATTERN; skip[c] = (uint8)(m - i); } for (k = start + m; k < textlen; k += ((c = text[k]) >= BMH_CHARSET_SIZE) ? patlen : skip[c]) { for (i = k, j = m; ; i--, j--) { if (j < 0) return i + 1; if (text[i] != pat[j]) break; } } return -1;}static JSBoolstr_indexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSString *str, *str2; jsint i, j, index, textlen, patlen; const jschar *text, *pat; jsdouble d; str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); if (!str) return JS_FALSE; argv[-1] = STRING_TO_JSVAL(str); text = JSSTRING_CHARS(str); textlen = (jsint) JSSTRING_LENGTH(str); str2 = js_ValueToString(cx, argv[0]); if (!str2) return JS_FALSE; argv[0] = STRING_TO_JSVAL(str2); pat = JSSTRING_CHARS(str2); patlen = (jsint) JSSTRING_LENGTH(str2); if (argc > 1) { if (!js_ValueToNumber(cx, argv[1], &d)) return JS_FALSE; d = js_DoubleToInteger(d); if (d < 0) i = 0; else if (d > textlen) i = textlen; else i = (jsint)d; } else { i = 0; } if (patlen == 0) { *rval = INT_TO_JSVAL(i); return JS_TRUE; } /* XXX tune the BMH threshold (512) */ if ((jsuint)(patlen - 2) <= BMH_PATLEN_MAX - 2 && textlen >= 512) { index = js_BoyerMooreHorspool(text, textlen, pat, patlen, i); if (index != BMH_BAD_PATTERN) goto out; } index = -1; j = 0; while (i + j < textlen) { if (text[i + j] == pat[j]) { if (++j == patlen) { index = i; break; } } else { i++; j = 0; } }out: *rval = INT_TO_JSVAL(index); return JS_TRUE;}static JSBoolstr_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSString *str, *str2; const jschar *text, *pat; jsint i, j, textlen, patlen; jsdouble d; str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); if (!str) return JS_FALSE; argv[-1] = STRING_TO_JSVAL(str); text = JSSTRING_CHARS(str); textlen = (jsint) JSSTRING_LENGTH(str); str2 = js_ValueToString(cx, argv[0]); if (!str2) return JS_FALSE; argv[0] = STRING_TO_JSVAL(str2); pat = JSSTRING_CHARS(str2); patlen = (jsint) JSSTRING_LENGTH(str2); if (argc > 1) { if (!js_ValueToNumber(cx, argv[1], &d)) return JS_FALSE; if (JSDOUBLE_IS_NaN(d)) { i = textlen; } else { d = js_DoubleToInteger(d); if (d < 0) i = 0; else if (d > textlen) i = textlen; else i = (jsint)d; } } else { i = textlen; } if (patlen == 0) { *rval = INT_TO_JSVAL(i); return JS_TRUE; } j = 0; while (i >= 0) { /* Don't assume that text is NUL-terminated: it could be dependent. */ if (i + j < textlen && text[i + j] == pat[j]) { if (++j == patlen) break; } else { i--; j = 0; } } *rval = INT_TO_JSVAL(i); return JS_TRUE;}/* * Perl-inspired string functions. */typedef struct GlobData { uintN flags; /* inout: mode and flag bits, see below */ uintN optarg; /* in: index of optional flags argument */ JSString *str; /* out: 'this' parameter object as string */ JSRegExp *regexp; /* out: regexp parameter object private data */} GlobData;/* * Mode and flag bit definitions for match_or_replace's GlobData.flags field. */#define MODE_MATCH 0x00 /* in: return match array on success */#define MODE_REPLACE 0x01 /* in: match and replace */#define MODE_SEARCH 0x02 /* in: search only, return match index or -1 */#define GET_MODE(f) ((f) & 0x03)#define FORCE_FLAT 0x04 /* in: force flat (non-regexp) string match */#define KEEP_REGEXP 0x08 /* inout: keep GlobData.regexp alive for caller of match_or_replace; if set on input but clear on output, regexp ownership does not pass to caller */#define GLOBAL_REGEXP 0x10 /* out: regexp had the 'g' flag */static JSBoolmatch_or_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, JSBool (*glob)(JSContext *cx, jsint count, GlobData *data), GlobData *data, jsval *rval){ JSString *str, *src, *opt; JSObject *reobj; JSRegExp *re; size_t index, length; JSBool ok, test; jsint count; str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj)); if (!str) return JS_FALSE; argv[-1] = STRING_TO_JSVAL(str); data->str = str; if (JSVAL_IS_REGEXP(cx, argv[0])) { reobj = JSVAL_TO_OBJECT(argv[0]); re = (JSRegExp *) JS_GetPrivate(cx, reobj); } else { src = js_ValueToString(cx, argv[0]); if (!src) return JS_FALSE; if (data->optarg < argc) { argv[0] = STRING_TO_JSVAL(src); opt = js_ValueToString(cx, argv[data->optarg]); if (!opt) return JS_FALSE; } else { opt = NULL; } re = js_NewRegExpOpt(cx, NULL, src, opt, (data->flags & FORCE_FLAT) != 0); if (!re) return JS_FALSE; reobj = NULL; } /* From here on, all control flow must reach the matching DROP. */ data->regexp = re; HOLD_REGEXP(cx, re); if (re->flags & JSREG_GLOB) data->flags |= GLOBAL_REGEXP; index = 0; if (GET_MODE(data->flags) == MODE_SEARCH) { ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval); if (ok) { *rval = (*rval == JSVAL_TRUE) ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length) : INT_TO_JSVAL(-1); } } else if (data->flags & GLOBAL_REGEXP) { if (reobj) { /* Set the lastIndex property's reserved slot to 0. */ ok = js_SetLastIndex(cx, reobj, 0); } else { ok = JS_TRUE; } if (ok) { length = JSSTRING_LENGTH(str); for (count = 0; index <= length; count++) { ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, rval); if (!ok || *rval != JSVAL_TRUE) break; ok = glob(cx, count, data); if (!ok) break; if (cx->regExpStatics.lastMatch.length == 0) { if (index == length) break; index++; } } } } else { if (GET_MODE(data->flags) == MODE_REPLACE) { test = JS_TRUE; } else { /* * MODE_MATCH implies str_match is being called from a script or a * scripted function. If the caller cares only about testing null * vs. non-null return value, optimize away the array object that * would normally be returned in *rval. */ JSStackFrame *fp = cx->fp->down; /* Skip Function.prototype.call and .apply frames. */ while (fp && !fp->pc) { JS_ASSERT(!fp->script); fp = fp->down; } /* Assume a full array result is required, then prove otherwise. */ test = JS_FALSE; if (fp) { JS_ASSERT(*fp->pc == JSOP_CALL || *fp->pc == JSOP_NEW); JS_ASSERT(js_CodeSpec[*fp->pc].length == 3); switch (fp->pc[3]) { case JSOP_POP: case JSOP_IFEQ: case JSOP_IFNE: case JSOP_IFEQX: case JSOP_IFNEX: test = JS_TRUE; break; default:; } } } ok = js_ExecuteRegExp(cx, re, str, &index, test, rval); } DROP_REGEXP(cx, re); if (reobj) { /* Tell our caller that it doesn't need to destroy data->regexp. */ data->flags &= ~KEEP_REGEXP; } else if (!(data->flags & KEEP_REGEXP)) { /* Caller didn't want to keep data->regexp, so null and destroy it. */ data->regexp = NULL; js_DestroyRegExp(cx, re); } return ok;}typedef struct MatchData { GlobData base; jsval *arrayval; /* NB: local root pointer */} MatchData;static JSBoolmatch_glob(JSContext *cx, jsint count, GlobData *data){ MatchData *mdata; JSObject *arrayobj; JSSubString *matchsub; JSString *matchstr; jsval v; mdata = (MatchData *)data; arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval); if (!arrayobj) { arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL); if (!arrayobj) return JS_FALSE; *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj); } matchsub = &cx->regExpStatics.lastMatch; matchstr = js_NewStringCopyN(cx, matchsub->chars, matchsub->length, 0); if (!matchstr) return JS_FALSE; v = STRING_TO_JSVAL(matchstr); return js_SetProperty(cx, arrayobj, INT_TO_JSID(count), &v);}static JSBoolstr_match(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ MatchData mdata; JSBool ok; mdata.base.flags = MODE_MATCH; mdata.base.optarg = 1; mdata.arrayval = &argv[2]; *mdata.arrayval = JSVAL_NULL; ok = match_or_replace(cx, obj, argc, argv, match_glob, &mdata.base, rval); if (ok && !JSVAL_IS_NULL(*mdata.arrayval)) *rval = *mdata.arrayval; return ok;}static JSBoolstr_search(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ GlobData data; data.flags = MODE_SEARCH; data.optarg = 1; return match_or_replace(cx, obj, argc, argv, NULL, &data, rval);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -