⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsstr.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
                    break;                num = tmp;            }        } else { /* ECMA 3, 1-9 or 01-99 */            num = JS7_UNDEC(dc);            if (num > res->parenCount)                return NULL;            cp = dp + 2;            dc = *cp;            if ((dc != 0) && JS7_ISDEC(dc)) {                tmp = 10 * num + JS7_UNDEC(dc);                if (tmp <= res->parenCount) {                    cp++;                    num = tmp;                }            }            if (num == 0)                return NULL;        }        /* Adjust num from 1 $n-origin to 0 array-index-origin. */        num--;        *skip = cp - dp;        return REGEXP_PAREN_SUBSTRING(res, num);    }    *skip = 2;    switch (dc) {      case '$':        rdata->dollarStr.chars = dp;        rdata->dollarStr.length = 1;        return &rdata->dollarStr;      case '&':        return &res->lastMatch;      case '+':        return &res->lastParen;      case '`':        if (cx->version == JSVERSION_1_2) {            /*             * JS1.2 imitated the Perl4 bug where left context at each step             * in an iterative use of a global regexp started from last match,             * not from the start of the target string.  But Perl4 does start             * $` at the beginning of the target string when it is used in a             * substitution, so we emulate that special case here.             */            str = rdata->base.str;            res->leftContext.chars = JSSTRING_CHARS(str);            res->leftContext.length = res->lastMatch.chars                                    - JSSTRING_CHARS(str);        }        return &res->leftContext;      case '\'':        return &res->rightContext;    }    return NULL;}static JSBoolfind_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep){    JSString *repstr;    size_t replen, skip;    jschar *dp, *ep;    JSSubString *sub;#if JS_HAS_REPLACE_LAMBDA    JSObject *lambda;    lambda = rdata->lambda;    if (lambda) {        uintN argc, i, j, m, n, p;        jsval *sp, *oldsp, rval;        void *mark;        JSStackFrame *fp;        JSBool ok;        /*         * Save the rightContext from the current regexp, since it         * gets stuck at the end of the replacement string and may         * be clobbered by a RegExp usage in the lambda function.         */        JSSubString saveRightContext = cx->regExpStatics.rightContext;        /*         * In the lambda case, not only do we find the replacement string's         * length, we compute repstr and return it via rdata for use within         * do_replace.  The lambda is called with arguments ($&, $1, $2, ...,         * index, input), i.e., all the properties of a regexp match array.         * For $&, etc., we must create string jsvals from cx->regExpStatics.         * We grab up stack space to keep the newborn strings GC-rooted.         */        p = rdata->base.regexp->parenCount;        argc = 1 + p + 2;        sp = js_AllocStack(cx, 2 + argc, &mark);        if (!sp)            return JS_FALSE;        /* Push lambda and its 'this' parameter. */        *sp++ = OBJECT_TO_JSVAL(lambda);        *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda));#define PUSH_REGEXP_STATIC(sub)                                               \    JS_BEGIN_MACRO                                                            \        JSString *str = js_NewStringCopyN(cx,                                 \                                          cx->regExpStatics.sub.chars,        \                                          cx->regExpStatics.sub.length,       \                                          0);                                 \        if (!str) {                                                           \            ok = JS_FALSE;                                                    \            goto lambda_out;                                                  \        }                                                                     \        *sp++ = STRING_TO_JSVAL(str);                                         \    JS_END_MACRO        /* Push $&, $1, $2, ... */        PUSH_REGEXP_STATIC(lastMatch);        i = 0;        m = cx->regExpStatics.parenCount;        n = JS_MIN(m, 9);        for (j = 0; i < n; i++, j++)            PUSH_REGEXP_STATIC(parens[j]);        for (j = 0; i < m; i++, j++)            PUSH_REGEXP_STATIC(moreParens[j]);#undef PUSH_REGEXP_STATIC        /* Make sure to push undefined for any unmatched parens. */        for (; i < p; i++)            *sp++ = JSVAL_VOID;        /* Push match index and input string. */        *sp++ = INT_TO_JSVAL((jsint)cx->regExpStatics.leftContext.length);        *sp++ = STRING_TO_JSVAL(rdata->base.str);        /* Lift current frame to include the args and do the call. */        fp = cx->fp;        oldsp = fp->sp;        fp->sp = sp;        ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL);        rval = fp->sp[-1];        fp->sp = oldsp;        if (ok) {            /*             * NB: we count on the newborn string root to hold any string             * created by this js_ValueToString that would otherwise be GC-             * able, until we use rdata->repstr in do_replace.             */            repstr = js_ValueToString(cx, rval);            if (!repstr) {                ok = JS_FALSE;            } else {                rdata->repstr = repstr;                *sizep = JSSTRING_LENGTH(repstr);            }        }      lambda_out:        js_FreeStack(cx, mark);        cx->regExpStatics.rightContext = saveRightContext;        return ok;    }#endif /* JS_HAS_REPLACE_LAMBDA */    repstr = rdata->repstr;    replen = JSSTRING_LENGTH(repstr);    for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;         dp = js_strchr_limit(dp, '$', ep)) {        sub = interpret_dollar(cx, dp, rdata, &skip);        if (sub) {            replen += sub->length - skip;            dp += skip;        }        else            dp++;    }    *sizep = replen;    return JS_TRUE;}static voiddo_replace(JSContext *cx, ReplaceData *rdata, jschar *chars){    JSString *repstr;    jschar *bp, *cp, *dp, *ep;    size_t len, skip;    JSSubString *sub;    repstr = rdata->repstr;    bp = cp = JSSTRING_CHARS(repstr);    for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;         dp = js_strchr_limit(dp, '$', ep)) {        len = dp - cp;        js_strncpy(chars, cp, len);        chars += len;        cp = dp;        sub = interpret_dollar(cx, dp, rdata, &skip);        if (sub) {            len = sub->length;            js_strncpy(chars, sub->chars, len);            chars += len;            cp += skip;            dp += skip;        } else {            dp++;        }    }    js_strncpy(chars, cp, JSSTRING_LENGTH(repstr) - (cp - bp));}static JSBoolreplace_glob(JSContext *cx, jsint count, GlobData *data){    ReplaceData *rdata;    JSString *str;    size_t leftoff, leftlen, replen, growth;    const jschar *left;    jschar *chars;    rdata = (ReplaceData *)data;    str = data->str;    leftoff = rdata->leftIndex;    left = JSSTRING_CHARS(str) + leftoff;    leftlen = cx->regExpStatics.lastMatch.chars - left;    rdata->leftIndex = cx->regExpStatics.lastMatch.chars - JSSTRING_CHARS(str);    rdata->leftIndex += cx->regExpStatics.lastMatch.length;    if (!find_replen(cx, rdata, &replen))        return JS_FALSE;    growth = leftlen + replen;    chars = (jschar *)        (rdata->chars         ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1)                                        * sizeof(jschar))         : JS_malloc(cx, (growth + 1) * sizeof(jschar)));    if (!chars) {        JS_free(cx, rdata->chars);        rdata->chars = NULL;        return JS_FALSE;    }    rdata->chars = chars;    rdata->length += growth;    chars += rdata->index;    rdata->index += growth;    js_strncpy(chars, left, leftlen);    chars += leftlen;    do_replace(cx, rdata, chars);    return JS_TRUE;}static JSBoolstr_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSObject *lambda;    JSString *repstr, *str;    ReplaceData rdata;    JSBool ok;    jschar *chars;    size_t leftlen, rightlen, length;#if JS_HAS_REPLACE_LAMBDA    if (JS_TypeOfValue(cx, argv[1]) == JSTYPE_FUNCTION) {        lambda = JSVAL_TO_OBJECT(argv[1]);        repstr = NULL;    } else#endif    {        if (!JS_ConvertValue(cx, argv[1], JSTYPE_STRING, &argv[1]))            return JS_FALSE;        repstr = JSVAL_TO_STRING(argv[1]);        lambda = NULL;    }    /*     * For ECMA Edition 3, the first argument is to be converted to a string     * to match in a "flat" sense (without regular expression metachars having     * special meanings) UNLESS the first arg is a RegExp object.     */    rdata.base.flags = MODE_REPLACE | KEEP_REGEXP;    if (cx->version == JSVERSION_DEFAULT || cx->version > JSVERSION_1_4)        rdata.base.flags |= FORCE_FLAT;    rdata.base.optarg = 2;    rdata.lambda = lambda;    rdata.repstr = repstr;    if (repstr) {        rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);        rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',                                       rdata.dollarEnd);    } else {        rdata.dollar = rdata.dollarEnd = NULL;    }    rdata.chars = NULL;    rdata.length = 0;    rdata.index = 0;    rdata.leftIndex = 0;    ok = match_or_replace(cx, obj, argc, argv, replace_glob, &rdata.base, rval);    if (!ok)        return JS_FALSE;    if (!rdata.chars) {        if ((rdata.base.flags & GLOBAL_REGEXP) || *rval != JSVAL_TRUE) {            /* Didn't match even once. */            *rval = STRING_TO_JSVAL(rdata.base.str);            goto out;        }        leftlen = cx->regExpStatics.leftContext.length;        ok = find_replen(cx, &rdata, &length);        if (!ok)            goto out;        length += leftlen;        chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));        if (!chars) {            ok = JS_FALSE;            goto out;        }        js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen);        do_replace(cx, &rdata, chars + leftlen);        rdata.chars = chars;        rdata.length = length;    }    rightlen = cx->regExpStatics.rightContext.length;    length = rdata.length + rightlen;    chars = (jschar *)        JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar));    if (!chars) {        JS_free(cx, rdata.chars);        ok = JS_FALSE;        goto out;    }    js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars,               rightlen);    chars[length] = 0;    str = js_NewString(cx, chars, length, 0);    if (!str) {        JS_free(cx, chars);        ok = JS_FALSE;        goto out;    }    *rval = STRING_TO_JSVAL(str);out:    /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */    if (rdata.base.flags & KEEP_REGEXP)        js_DestroyRegExp(cx, rdata.base.regexp);    return ok;}#endif /* JS_HAS_REGEXPS *//* * Subroutine used by str_split to find the next split point in str, starting * at offset *ip and looking either for the separator substring given by sep, * or for the next re match.  In the re case, return the matched separator in * *sep, and the possibly updated offset in *ip. * * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next * separator occurrence if found, or str->length if no separator is found. */static jsintfind_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,           JSSubString *sep){    jsint i, j, k;    jschar *chars;    size_t length;    /*     * Stop if past end of string.  If at end of string, we will compare the     * null char stored there (by js_NewString*) to sep->chars[j] in the while     * loop at the end of this function, so that     *     *  "ab,".split(',') => ["ab", ""]     *     * and the resulting array converts back to the string "ab," for symmetry.     * However, we ape Perl and do this only if there is a sufficiently large     * limit argument (see str_split).     */    i = *ip;    if ((size_t)i > JSSTRING_LENGTH(str))        return -1;    /*     * Perl4 special case for str.split(' '), only if the user has selected     * JavaScript1.2 explicitly.  Split on whitespace, and skip leading w/s.     * Strange but true, apparently modeled after awk.     *     * NB: we set sep->length to the length of the w/s run, so we must test     * sep->chars[1] == 0 to make sure sep is just one space.     */    chars = JSSTRING_CHARS(str);    length = JSSTRING_LENGTH(str);    if (cx->version == JSVERSION_1_2 &&        !re && *sep->chars == ' ' && sep->chars[1] == 0) {        /* Skip leading whitespace if at front of str. */        if (i == 0) {            while (JS_ISSPACE(chars[i]))                i++;            *ip = i;        }        /* Don't delimit whitespace at end of string. */        if ((size_t)i == length)            return -1;        /* Skip over the non-whitespace chars. */        while ((size_t)i < length && !JS_ISSPACE(chars[i]))            i++;        /* Now skip the next run of whitespace. */        j = i;        while ((size_t)j < length && JS_ISSPACE(chars[j]))            j++;        /* Update sep->length to count delimiter chars. */        sep->length = (size_t)(j - i);        return i;    }#if JS_HAS_REGEXPS    /*     * Match a regular expression against the separator at or above index i.     * Call js_ExecuteRegExp with true for the test argument.  On successful     * match, get the separator from cx->regExpStatics.lastMatch.     */    if (re) {        size_t index;        jsval rval;      again:        /* JS1.2 deviated from Perl by never matching at end of string. */        index = (size_t)i;        if (!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &rval))            return -2;        if (rval != JSVAL_TRUE) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -