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

📄 jsstr.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
}typedef struct ReplaceData {    GlobData    base;           /* base struct state */    JSObject    *lambda;        /* replacement function object or null */    JSString    *repstr;        /* replacement string */    jschar      *dollar;        /* null or pointer to first $ in repstr */    jschar      *dollarEnd;     /* limit pointer for js_strchr_limit */    jschar      *chars;         /* result chars, null initially */    size_t      length;         /* result length, 0 initially */    jsint       index;          /* index in result of next replacement */    jsint       leftIndex;      /* left context index in base.str->chars */    JSSubString dollarStr;      /* for "$$" interpret_dollar result */} ReplaceData;static JSSubString *interpret_dollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData *rdata,                 size_t *skip){    JSRegExpStatics *res;    jschar dc, *cp;    uintN num, tmp;    JS_ASSERT(*dp == '$');    /* If there is only a dollar, bail now */    if (dp + 1 >= ep)        return NULL;    /* Interpret all Perl match-induced dollar variables. */    res = &cx->regExpStatics;    dc = dp[1];    if (JS7_ISDEC(dc)) {        /* ECMA-262 Edition 3: 1-9 or 01-99 */        num = JS7_UNDEC(dc);        if (num > res->parenCount)            return NULL;        cp = dp + 2;        if (cp < ep && (dc = *cp, 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 '`':        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;    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 regExpStatics from the current regexp, since they may be         * clobbered by a RegExp usage in the lambda function.  Note that all         * members of JSRegExpStatics are JSSubStrings, so not GC roots, save         * input, which is rooted otherwise via argv[-1] in str_replace.         */        JSRegExpStatics save = cx->regExpStatics;        JSBool freeMoreParens = JS_FALSE;        /*         * 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]);        /*         * We need to clear moreParens in the top-of-stack cx->regExpStatics         * to it won't be possibly realloc'ed, leaving the bottom-of-stack         * moreParens pointing to freed memory.         */        cx->regExpStatics.moreParens = NULL;        freeMoreParens = JS_TRUE;#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);        if (freeMoreParens)            JS_free(cx, cx->regExpStatics.moreParens);        cx->regExpStatics = save;        return ok;    }    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, ep, 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, ep, 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_TypeOfValue(cx, argv[1]) == JSTYPE_FUNCTION) {        lambda = JSVAL_TO_OBJECT(argv[1]);        repstr = NULL;    } else {        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 | 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;}/* * 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;    size_t length;    jschar *chars;    /*     * 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;    length = JSSTRING_LENGTH(str);    if ((size_t)i > length)        return -1;    chars = JSSTRING_CHARS(str);    /*     * 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) {            /* Mismatch: ensure our caller advances i past end of string. */            sep->length = 1;            return length;        }        i = (jsint)index;        *sep = cx->regExpStatics.lastMatch;        if (sep->length == 0) {            /*             * Empty string match: never split on an empty match at the start             * of a find_split cycle.  Same rule as for an empty global match             * in match_or_replace.             */            if (i == *ip) {                /*                 * "Bump-along" to avoid sticking at an empty match, but don't                 * bump past end of string -- our caller must do that by adding                 * sep->length to our return value.                 */

⌨️ 快捷键说明

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