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

📄 jsstr.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=80: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS string type implementation. * * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these * native methods store strings (possibly newborn) converted from their 'this' * parameter and arguments on the stack: 'this' conversions at argv[-1], arg * conversions at their index (argv[0], argv[1]).  This is a legitimate method * of rooting things that might lose their newborn root due to subsequent GC * allocations in the same native method. */#include "jsstddef.h"#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsutil.h" /* Added by JSIFY */#include "jshash.h" /* Added by JSIFY */#include "jsprf.h"#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jsbool.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsgc.h"#include "jsinterp.h"#include "jslock.h"#include "jsnum.h"#include "jsobj.h"#include "jsopcode.h"#include "jsregexp.h"#include "jsstr.h"#define JSSTRDEP_RECURSION_LIMIT        100size_tjs_MinimizeDependentStrings(JSString *str, int level, JSString **basep){    JSString *base;    size_t start, length;    JS_ASSERT(JSSTRING_IS_DEPENDENT(str));    base = JSSTRDEP_BASE(str);    start = JSSTRDEP_START(str);    if (JSSTRING_IS_DEPENDENT(base)) {        if (level < JSSTRDEP_RECURSION_LIMIT) {            start += js_MinimizeDependentStrings(base, level + 1, &base);        } else {            do {                start += JSSTRDEP_START(base);                base = JSSTRDEP_BASE(base);            } while (JSSTRING_IS_DEPENDENT(base));        }        if (start == 0) {            JS_ASSERT(JSSTRING_IS_PREFIX(str));            JSPREFIX_SET_BASE(str, base);        } else if (start <= JSSTRDEP_START_MASK) {            length = JSSTRDEP_LENGTH(str);            JSSTRDEP_SET_START_AND_LENGTH(str, start, length);            JSSTRDEP_SET_BASE(str, base);        }    }    *basep = base;    return start;}jschar *js_GetDependentStringChars(JSString *str){    size_t start;    JSString *base;    start = js_MinimizeDependentStrings(str, 0, &base);    JS_ASSERT(!JSSTRING_IS_DEPENDENT(base));    JS_ASSERT(start < base->length);    return base->chars + start;}jschar *js_GetStringChars(JSString *str){    if (JSSTRING_IS_DEPENDENT(str) && !js_UndependString(NULL, str))        return NULL;    *js_GetGCThingFlags(str) &= ~GCF_MUTABLE;    return str->chars;}JSString *js_ConcatStrings(JSContext *cx, JSString *left, JSString *right){    size_t rn, ln, lrdist, n;    jschar *rs, *ls, *s;    JSDependentString *ldep;    /* non-null if left should become dependent */    JSString *str;    if (JSSTRING_IS_DEPENDENT(right)) {        rn = JSSTRDEP_LENGTH(right);        rs = JSSTRDEP_CHARS(right);    } else {        rn = right->length;        rs = right->chars;    }    if (rn == 0)        return left;    if (JSSTRING_IS_DEPENDENT(left) ||        !(*js_GetGCThingFlags(left) & GCF_MUTABLE)) {        /* We must copy if left does not own a buffer to realloc. */        ln = JSSTRING_LENGTH(left);        if (ln == 0)            return right;        ls = JSSTRING_CHARS(left);        s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar));        if (!s)            return NULL;        js_strncpy(s, ls, ln);        ldep = NULL;    } else {        /* We can realloc left's space and make it depend on our result. */        ln = left->length;        if (ln == 0)            return right;        ls = left->chars;        s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar));        if (!s)            return NULL;        /* Take care: right could depend on left! */        lrdist = (size_t)(rs - ls);        if (lrdist < ln)            rs = s + lrdist;        left->chars = ls = s;        ldep = JSSTRDEP(left);    }    js_strncpy(s + ln, rs, rn);    n = ln + rn;    s[n] = 0;    str = js_NewString(cx, s, n, GCF_MUTABLE);    if (!str) {        /* Out of memory: clean up any space we (re-)allocated. */        if (!ldep) {            JS_free(cx, s);        } else {            s = JS_realloc(cx, ls, (ln + 1) * sizeof(jschar));            if (s)                left->chars = s;        }    } else {        /* Morph left into a dependent prefix if we realloc'd its buffer. */        if (ldep) {            JSPREFIX_SET_LENGTH(ldep, ln);            JSPREFIX_SET_BASE(ldep, str);#ifdef DEBUG          {            JSRuntime *rt = cx->runtime;            JS_RUNTIME_METER(rt, liveDependentStrings);            JS_RUNTIME_METER(rt, totalDependentStrings);            JS_LOCK_RUNTIME_VOID(rt,                (rt->strdepLengthSum += (double)ln,                 rt->strdepLengthSquaredSum += (double)ln * (double)ln));          }#endif        }    }    return str;}/* * May be called with null cx by js_GetStringChars, above; and by the jslock.c * MAKE_STRING_IMMUTABLE file-local macro. */const jschar *js_UndependString(JSContext *cx, JSString *str){    size_t n, size;    jschar *s;    if (JSSTRING_IS_DEPENDENT(str)) {        n = JSSTRDEP_LENGTH(str);        size = (n + 1) * sizeof(jschar);        s = (jschar *) (cx ? JS_malloc(cx, size) : malloc(size));        if (!s)            return NULL;        js_strncpy(s, JSSTRDEP_CHARS(str), n);        s[n] = 0;        str->length = n;        str->chars = s;#ifdef DEBUG        if (cx) {            JSRuntime *rt = cx->runtime;            JS_RUNTIME_UNMETER(rt, liveDependentStrings);            JS_RUNTIME_UNMETER(rt, totalDependentStrings);            JS_LOCK_RUNTIME_VOID(rt,                (rt->strdepLengthSum -= (double)n,                 rt->strdepLengthSquaredSum -= (double)n * (double)n));        }#endif    }    return str->chars;}/* * Forward declarations for URI encode/decode and helper routines */static JSBoolstr_decodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval);static JSBoolstr_decodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,                        jsval *rval);static JSBoolstr_encodeURI(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,              jsval *rval);static JSBoolstr_encodeURI_Component(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,                        jsval *rval);static uint32Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length);/* * Contributions from the String class to the set of methods defined for the * global object.  escape and unescape used to be defined in the Mocha library, * but as ECMA decided to spec them, they've been moved to the core engine * and made ECMA-compliant.  (Incomplete escapes are interpreted as literal * characters by unescape.) *//* * Stuff to emulate the old libmocha escape, which took a second argument * giving the type of escape to perform.  Retained for compatibility, and * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes. */#define URL_XALPHAS     ((uint8) 1)#define URL_XPALPHAS    ((uint8) 2)#define URL_PATH        ((uint8) 4)static const uint8 urlCharType[256] =/*      Bit 0           xalpha          -- the alphas *      Bit 1           xpalpha         -- as xalpha but *                             converts spaces to plus and plus to %20 *      Bit 2 ...       path            -- as xalphas but doesn't escape '/' */    /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */    {    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,       /* 0x */         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,       /* 1x */         0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4,       /* 2x   !"#$%&'()*+,-./  */         7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,       /* 3x  0123456789:;<=>?  */         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 4x  @ABCDEFGHIJKLMNO  */         7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7,       /* 5X  PQRSTUVWXYZ[\]^_  */         0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 6x  `abcdefghijklmno  */         7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,       /* 7X  pqrstuvwxyz{\}~  DEL */         0, };/* This matches the ECMA escape set when mask is 7 (default.) */#define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))/* See ECMA-262 15.1.2.4. */JSBooljs_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSString *str;    size_t i, ni, length, newlength;    const jschar *chars;    jschar *newchars;    jschar ch;    jsint mask;    jsdouble d;    const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',                           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };    mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;    if (argc > 1) {        if (!js_ValueToNumber(cx, argv[1], &d))            return JS_FALSE;        if (!JSDOUBLE_IS_FINITE(d) ||            (mask = (jsint)d) != d ||            mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))        {            char numBuf[12];            JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                 JSMSG_BAD_STRING_MASK, numBuf);            return JS_FALSE;        }    }    str = js_ValueToString(cx, argv[0]);    if (!str)        return JS_FALSE;    argv[0] = STRING_TO_JSVAL(str);    chars = JSSTRING_CHARS(str);    length = newlength = JSSTRING_LENGTH(str);    /* Take a first pass and see how big the result string will need to be. */    for (i = 0; i < length; i++) {        if ((ch = chars[i]) < 128 && IS_OK(ch, mask))            continue;        if (ch < 256) {            if (mask == URL_XPALPHAS && ch == ' ')                continue;   /* The character will be encoded as '+' */            newlength += 2; /* The character will be encoded as %XX */        } else {            newlength += 5; /* The character will be encoded as %uXXXX */        }        /*         * This overflow test works because newlength is incremented by at         * most 5 on each iteration.         */        if (newlength < length) {            JS_ReportOutOfMemory(cx);            return JS_FALSE;        }    }    if (newlength >= ~(size_t)0 / sizeof(jschar)) {        JS_ReportOutOfMemory(cx);        return JS_FALSE;    }    newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar));    if (!newchars)        return JS_FALSE;    for (i = 0, ni = 0; i < length; i++) {        if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {            newchars[ni++] = ch;        } else if (ch < 256) {            if (mask == URL_XPALPHAS && ch == ' ') {                newchars[ni++] = '+'; /* convert spaces to pluses */            } else {                newchars[ni++] = '%';                newchars[ni++] = digits[ch >> 4];                newchars[ni++] = digits[ch & 0xF];            }        } else {            newchars[ni++] = '%';            newchars[ni++] = 'u';            newchars[ni++] = digits[ch >> 12];            newchars[ni++] = digits[(ch & 0xF00) >> 8];            newchars[ni++] = digits[(ch & 0xF0) >> 4];            newchars[ni++] = digits[ch & 0xF];        }    }    JS_ASSERT(ni == newlength);    newchars[newlength] = 0;    str = js_NewString(cx, newchars, newlength, 0);    if (!str) {        JS_free(cx, newchars);        return JS_FALSE;    }    *rval = STRING_TO_JSVAL(str);    return JS_TRUE;}#undef IS_OK/* See ECMA-262 15.1.2.5 */static JSBoolstr_unescape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSString *str;    size_t i, ni, length;    const jschar *chars;    jschar *newchars;    jschar ch;    str = js_ValueToString(cx, argv[0]);    if (!str)        return JS_FALSE;    argv[0] = STRING_TO_JSVAL(str);    chars = JSSTRING_CHARS(str);    length = JSSTRING_LENGTH(str);    /* Don't bother allocating less space for the new string. */    newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));    if (!newchars)        return JS_FALSE;    ni = i = 0;    while (i < length) {        ch = chars[i++];        if (ch == '%') {            if (i + 1 < length &&                JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))            {                ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]);

⌨️ 快捷键说明

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