📄 jsxdrapi.c
字号:
nbytes = nchars * sizeof(jschar); padlen = nbytes % JSXDR_ALIGN; if (padlen) { padlen = JSXDR_ALIGN - padlen; nbytes += padlen; } if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes))) return JS_FALSE; if (xdr->mode == JSXDR_ENCODE) { for (i = 0; i != nchars; i++) raw[i] = JSXDR_SWAB16(chars[i]); if (padlen) memset((char *)raw + nbytes - padlen, 0, padlen); } else if (xdr->mode == JSXDR_DECODE) { for (i = 0; i != nchars; i++) chars[i] = JSXDR_SWAB16(raw[i]); } return JS_TRUE;}/* * Convert between a JS (Unicode) string and the XDR representation. */JS_PUBLIC_API(JSBool)JS_XDRString(JSXDRState *xdr, JSString **strp){ uint32 nchars; jschar *chars; if (xdr->mode == JSXDR_ENCODE) nchars = JSSTRING_LENGTH(*strp); if (!JS_XDRUint32(xdr, &nchars)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) { chars = (jschar *) JS_malloc(xdr->cx, (nchars + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; } else { chars = JSSTRING_CHARS(*strp); } if (!XDRChars(xdr, chars, nchars)) goto bad; if (xdr->mode == JSXDR_DECODE) { chars[nchars] = 0; *strp = JS_NewUCString(xdr->cx, chars, nchars); if (!*strp) goto bad; } return JS_TRUE;bad: if (xdr->mode == JSXDR_DECODE) JS_free(xdr->cx, chars); return JS_FALSE;}JS_PUBLIC_API(JSBool)JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp){ uint32 null = (*strp == NULL); if (!JS_XDRUint32(xdr, &null)) return JS_FALSE; if (null) { *strp = NULL; return JS_TRUE; } return JS_XDRString(xdr, strp);}static JSBoolXDRDoubleValue(JSXDRState *xdr, jsdouble *dp){ jsdpun u; if (xdr->mode == JSXDR_ENCODE) u.d = *dp; if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *dp = u.d; return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_XDRDouble(JSXDRState *xdr, jsdouble **dpp){ jsdouble d; if (xdr->mode == JSXDR_ENCODE) d = **dpp; if (!XDRDoubleValue(xdr, &d)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) { *dpp = JS_NewDouble(xdr->cx, d); if (!*dpp) return JS_FALSE; } return JS_TRUE;}/* These are magic pseudo-tags: see jsapi.h, near the top, for real tags. */#define JSVAL_XDRNULL 0x8#define JSVAL_XDRVOID 0xAstatic JSBoolXDRValueBody(JSXDRState *xdr, uint32 type, jsval *vp){ switch (type) { case JSVAL_XDRNULL: *vp = JSVAL_NULL; break; case JSVAL_XDRVOID: *vp = JSVAL_VOID; break; case JSVAL_STRING: { JSString *str; if (xdr->mode == JSXDR_ENCODE) str = JSVAL_TO_STRING(*vp); if (!JS_XDRString(xdr, &str)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *vp = STRING_TO_JSVAL(str); break; } case JSVAL_DOUBLE: { jsdouble *dp; if (xdr->mode == JSXDR_ENCODE) dp = JSVAL_TO_DOUBLE(*vp); if (!JS_XDRDouble(xdr, &dp)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *vp = DOUBLE_TO_JSVAL(dp); break; } case JSVAL_OBJECT: { JSObject *obj; if (xdr->mode == JSXDR_ENCODE) obj = JSVAL_TO_OBJECT(*vp); if (!js_XDRObject(xdr, &obj)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *vp = OBJECT_TO_JSVAL(obj); break; } case JSVAL_BOOLEAN: { uint32 b; if (xdr->mode == JSXDR_ENCODE) b = (uint32) JSVAL_TO_BOOLEAN(*vp); if (!JS_XDRUint32(xdr, &b)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *vp = BOOLEAN_TO_JSVAL((JSBool) b); break; } default: { uint32 i; JS_ASSERT(type & JSVAL_INT); if (xdr->mode == JSXDR_ENCODE) i = (uint32) JSVAL_TO_INT(*vp); if (!JS_XDRUint32(xdr, &i)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) *vp = INT_TO_JSVAL((int32) i); break; } } return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_XDRValue(JSXDRState *xdr, jsval *vp){ uint32 type; if (xdr->mode == JSXDR_ENCODE) { if (JSVAL_IS_NULL(*vp)) type = JSVAL_XDRNULL; else if (JSVAL_IS_VOID(*vp)) type = JSVAL_XDRVOID; else type = JSVAL_TAG(*vp); } return JS_XDRUint32(xdr, &type) && XDRValueBody(xdr, type, vp);}JSBooljs_XDRAtom(JSXDRState *xdr, JSAtom **atomp){ jsval v; uint32 type; jsdouble d; JSAtom *atom; if (xdr->mode == JSXDR_ENCODE) { v = ATOM_KEY(*atomp); return JS_XDRValue(xdr, &v); } /* * Inline JS_XDRValue when decoding to avoid ceation of GC things when * then corresponding atom already exists. See bug 321985. */ if (!JS_XDRUint32(xdr, &type)) return JS_FALSE; if (type == JSVAL_STRING) return js_XDRStringAtom(xdr, atomp); if (type == JSVAL_DOUBLE) { if (!XDRDoubleValue(xdr, &d)) return JS_FALSE; atom = js_AtomizeDouble(xdr->cx, d, 0); } else { if (!XDRValueBody(xdr, type, &v)) return JS_FALSE; atom = js_AtomizeValue(xdr->cx, v, 0); } if (!atom) return JS_FALSE; *atomp = atom; return JS_TRUE;}extern JSBooljs_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp){ JSString *str; uint32 nchars; JSAtom *atom; JSContext *cx; void *mark; jschar *chars; if (xdr->mode == JSXDR_ENCODE) { JS_ASSERT(ATOM_IS_STRING(*atomp)); str = ATOM_TO_STRING(*atomp); return JS_XDRString(xdr, &str); } /* * Inline JS_XDRString when decoding to avoid JSString allocation * for already existing atoms. See bug 321985. */ if (!JS_XDRUint32(xdr, &nchars)) return JS_FALSE; atom = NULL; cx = xdr->cx; mark = JS_ARENA_MARK(&cx->tempPool); JS_ARENA_ALLOCATE_CAST(chars, jschar *, &cx->tempPool, nchars * sizeof(jschar)); if (!chars) JS_ReportOutOfMemory(cx); else if (XDRChars(xdr, chars, nchars)) atom = js_AtomizeChars(cx, chars, nchars, 0); JS_ARENA_RELEASE(&cx->tempPool, mark); if (!atom) return JS_FALSE; *atomp = atom; return JS_TRUE;}/* * FIXME: This performs lossy conversion and we need to switch to * js_XDRStringAtom while allowing to read older XDR files. See bug 325202. */JSBooljs_XDRCStringAtom(JSXDRState *xdr, JSAtom **atomp){ char *bytes; uint32 nbytes; JSAtom *atom; JSContext *cx; void *mark; if (xdr->mode == JSXDR_ENCODE) { JS_ASSERT(ATOM_IS_STRING(*atomp)); bytes = JS_GetStringBytes(ATOM_TO_STRING(*atomp)); return JS_XDRCString(xdr, &bytes); } /* * Inline JS_XDRCString when decoding not to malloc temporary buffer * just to free it after atomization. See bug 321985. */ if (!JS_XDRUint32(xdr, &nbytes)) return JS_FALSE; atom = NULL; cx = xdr->cx; mark = JS_ARENA_MARK(&cx->tempPool); JS_ARENA_ALLOCATE_CAST(bytes, char *, &cx->tempPool, nbytes * sizeof *bytes); if (!bytes) JS_ReportOutOfMemory(cx); else if (JS_XDRBytes(xdr, bytes, nbytes)) atom = js_Atomize(cx, bytes, nbytes, 0); JS_ARENA_RELEASE(&cx->tempPool, mark); if (!atom) return JS_FALSE; *atomp = atom; return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_XDRScript(JSXDRState *xdr, JSScript **scriptp){ if (!js_XDRScript(xdr, scriptp, NULL)) return JS_FALSE; if (xdr->mode == JSXDR_DECODE) js_CallNewScriptHook(xdr->cx, *scriptp, NULL); return JS_TRUE;}#define CLASS_REGISTRY_MIN 8#define CLASS_INDEX_TO_ID(i) ((i)+1)#define CLASS_ID_TO_INDEX(id) ((id)-1)typedef struct JSRegHashEntry { JSDHashEntryHdr hdr; const char *name; uint32 index;} JSRegHashEntry;JS_PUBLIC_API(JSBool)JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp){ uintN numclasses, maxclasses; JSClass **registry; numclasses = xdr->numclasses; maxclasses = xdr->maxclasses; if (numclasses == maxclasses) { maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1; registry = (JSClass **) JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *)); if (!registry) return JS_FALSE; xdr->registry = registry; xdr->maxclasses = maxclasses; } else { JS_ASSERT(numclasses && numclasses < maxclasses); registry = xdr->registry; } registry[numclasses] = clasp; if (xdr->reghash) { JSRegHashEntry *entry = (JSRegHashEntry *) JS_DHashTableOperate(xdr->reghash, clasp->name, JS_DHASH_ADD); if (!entry) { JS_ReportOutOfMemory(xdr->cx); return JS_FALSE; } entry->name = clasp->name; entry->index = numclasses; } *idp = CLASS_INDEX_TO_ID(numclasses); xdr->numclasses = ++numclasses; return JS_TRUE;}JS_PUBLIC_API(uint32)JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name){ uintN i, numclasses; numclasses = xdr->numclasses; if (numclasses >= 10) { JSRegHashEntry *entry; /* Bootstrap reghash from registry on first overpopulated Find. */ if (!xdr->reghash) { xdr->reghash = JS_NewDHashTable(JS_DHashGetStubOps(), NULL, sizeof(JSRegHashEntry), numclasses); if (xdr->reghash) { for (i = 0; i < numclasses; i++) { JSClass *clasp = xdr->registry[i]; entry = (JSRegHashEntry *) JS_DHashTableOperate(xdr->reghash, clasp->name, JS_DHASH_ADD); entry->name = clasp->name; entry->index = i; } } } /* If we managed to create reghash, use it for O(1) Find. */ if (xdr->reghash) { entry = (JSRegHashEntry *) JS_DHashTableOperate(xdr->reghash, name, JS_DHASH_LOOKUP); if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) return CLASS_INDEX_TO_ID(entry->index); } } /* Only a few classes, or we couldn't malloc reghash: use linear search. */ for (i = 0; i < numclasses; i++) { if (!strcmp(name, xdr->registry[i]->name)) return CLASS_INDEX_TO_ID(i); } return 0;}JS_PUBLIC_API(JSClass *)JS_XDRFindClassById(JSXDRState *xdr, uint32 id){ uintN i = CLASS_ID_TO_INDEX(id); if (i >= xdr->numclasses) return NULL; return xdr->registry[i];}#endif /* JS_HAS_XDR */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -