📄 jsxml.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=78: * * ***** 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 SpiderMonkey E4X code, released August, 2004. * * 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 ***** */#include "jsstddef.h"#include "jsconfig.h"#if JS_HAS_XML_SUPPORT#include <math.h>#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsbit.h"#include "jsprf.h"#include "jsutil.h"#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jsbool.h"#include "jscntxt.h"#include "jsfun.h"#include "jsgc.h"#include "jsinterp.h"#include "jslock.h"#include "jsnum.h"#include "jsobj.h"#include "jsopcode.h"#include "jsparse.h"#include "jsscan.h"#include "jsscope.h"#include "jsscript.h"#include "jsstr.h"#include "jsxml.h"#ifdef DEBUG#include <string.h> /* for #ifdef DEBUG memset calls */#endif/* * NOTES * - in the js shell, you must use the -x command line option, or call * options('xml') before compiling anything that uses XML literals * * TODO * - XXXbe patrol * - Fuse objects and their JSXML* private data into single GC-things * - fix function::foo vs. x.(foo == 42) collision using proper namespacing * - fix the !TCF_HAS_DEFXMLNS optimization in js_FoldConstants * - JSCLASS_DOCUMENT_OBSERVER support -- live two-way binding to Gecko's DOM! * - JS_TypeOfValue sure could use a cleaner interface to "types" */#ifdef DEBUG_brendan#define METERING 1#endif#ifdef METERINGstatic struct { jsrefcount qname; jsrefcount qnameobj; jsrefcount liveqname; jsrefcount liveqnameobj; jsrefcount namespace; jsrefcount namespaceobj; jsrefcount livenamespace; jsrefcount livenamespaceobj; jsrefcount xml; jsrefcount xmlobj; jsrefcount livexml; jsrefcount livexmlobj;} xml_stats;#define METER(x) JS_ATOMIC_INCREMENT(&(x))#define UNMETER(x) JS_ATOMIC_DECREMENT(&(x))#else#define METER(x) /* nothing */#define UNMETER(x) /* nothing */#endif/* * Random utilities and global functions. */const char js_isXMLName_str[] = "isXMLName";const char js_XMLList_str[] = "XMLList";const char js_localName_str[] = "localName";const char js_xml_parent_str[] = "parent";const char js_prefix_str[] = "prefix";const char js_toXMLString_str[] = "toXMLString";const char js_uri_str[] = "uri";const char js_amp_entity_str[] = "&";const char js_gt_entity_str[] = ">";const char js_lt_entity_str[] = "<";const char js_quot_entity_str[] = """;#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*')static JSBoolxml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ *rval = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argv[0])); return JS_TRUE;}/* * Namespace class and library functions. */enum namespace_tinyid { NAMESPACE_PREFIX = -1, NAMESPACE_URI = -2};static JSBoolnamespace_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp){ JSXMLNamespace *ns; if (!JSVAL_IS_INT(id)) return JS_TRUE; ns = (JSXMLNamespace *) JS_GetInstancePrivate(cx, obj, &js_NamespaceClass.base, NULL); if (!ns) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case NAMESPACE_PREFIX: *vp = ns->prefix ? STRING_TO_JSVAL(ns->prefix) : JSVAL_VOID; break; case NAMESPACE_URI: *vp = STRING_TO_JSVAL(ns->uri); break; } return JS_TRUE;}static voidnamespace_finalize(JSContext *cx, JSObject *obj){ JSXMLNamespace *ns; JSRuntime *rt; ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); if (!ns) return; JS_ASSERT(ns->object == obj); ns->object = NULL; UNMETER(xml_stats.livenamespaceobj); rt = cx->runtime; if (rt->functionNamespaceObject == obj) rt->functionNamespaceObject = NULL;}static voidnamespace_mark_vector(JSContext *cx, JSXMLNamespace **vec, uint32 len){ uint32 i; JSXMLNamespace *ns; for (i = 0; i < len; i++) { ns = vec[i]; {#ifdef GC_MARK_DEBUG char buf[100]; JS_snprintf(buf, sizeof buf, "%s=%s", ns->prefix ? JS_GetStringBytes(ns->prefix) : "", JS_GetStringBytes(ns->uri));#endif GC_MARK(cx, ns, buf); } }}static uint32namespace_mark(JSContext *cx, JSObject *obj, void *arg){ JSXMLNamespace *ns; ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); GC_MARK(cx, ns, "private"); return 0;}static JSBoolnamespace_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp){ JSXMLNamespace *ns, *ns2; JSObject *obj2; ns = (JSXMLNamespace *) JS_GetPrivate(cx, obj); JS_ASSERT(JSVAL_IS_OBJECT(v)); obj2 = JSVAL_TO_OBJECT(v); if (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_NamespaceClass.base) { *bp = JS_FALSE; } else { ns2 = (JSXMLNamespace *) JS_GetPrivate(cx, obj2); *bp = js_EqualStrings(ns->uri, ns2->uri); } return JS_TRUE;}JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = { { "Namespace", JSCLASS_HAS_PRIVATE | JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace), JS_PropertyStub, JS_PropertyStub, namespace_getProperty, NULL, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, namespace_finalize, NULL, NULL, NULL, NULL, NULL, NULL, namespace_mark, NULL }, namespace_equality,NULL, NULL, NULL, NULL, NULL, NULL, NULL};#define NAMESPACE_ATTRS \ (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)static JSPropertySpec namespace_props[] = { {js_prefix_str, NAMESPACE_PREFIX, NAMESPACE_ATTRS, 0, 0}, {js_uri_str, NAMESPACE_URI, NAMESPACE_ATTRS, 0, 0}, {0,0,0,0,0}};static JSBoolnamespace_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSXMLNamespace *ns; ns = (JSXMLNamespace *) JS_GetInstancePrivate(cx, obj, &js_NamespaceClass.base, argv); if (!ns) return JS_FALSE; *rval = STRING_TO_JSVAL(ns->uri); return JS_TRUE;}static JSFunctionSpec namespace_methods[] = { {js_toString_str, namespace_toString, 0,0,0}, {0,0,0,0,0}};JSXMLNamespace *js_NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared){ JSXMLNamespace *ns; ns = (JSXMLNamespace *) js_NewGCThing(cx, GCX_NAMESPACE, sizeof(JSXMLNamespace)); if (!ns) return NULL; ns->object = NULL; ns->prefix = prefix; ns->uri = uri; ns->declared = declared; METER(xml_stats.namespace); METER(xml_stats.livenamespace); return ns;}voidjs_MarkXMLNamespace(JSContext *cx, JSXMLNamespace *ns){ GC_MARK(cx, ns->object, "object"); GC_MARK(cx, ns->prefix, "prefix"); GC_MARK(cx, ns->uri, "uri");}voidjs_FinalizeXMLNamespace(JSContext *cx, JSXMLNamespace *ns){ UNMETER(xml_stats.livenamespace);}JSObject *js_NewXMLNamespaceObject(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared){ JSXMLNamespace *ns; ns = js_NewXMLNamespace(cx, prefix, uri, declared); if (!ns) return NULL; return js_GetXMLNamespaceObject(cx, ns);}JSObject *js_GetXMLNamespaceObject(JSContext *cx, JSXMLNamespace *ns){ JSObject *obj; obj = ns->object; if (obj) { JS_ASSERT(JS_GetPrivate(cx, obj) == ns); return obj; } obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL); if (!obj || !JS_SetPrivate(cx, obj, ns)) { cx->weakRoots.newborn[GCX_OBJECT] = NULL; return NULL; } ns->object = obj; METER(xml_stats.namespaceobj); METER(xml_stats.livenamespaceobj); return obj;}/* * QName class and library functions. */enum qname_tinyid { QNAME_URI = -1, QNAME_LOCALNAME = -2};static JSBoolqname_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp){ JSXMLQName *qn; if (!JSVAL_IS_INT(id)) return JS_TRUE; qn = (JSXMLQName *) JS_GetInstancePrivate(cx, obj, &js_QNameClass.base, NULL); if (!qn) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case QNAME_URI: *vp = qn->uri ? STRING_TO_JSVAL(qn->uri) : JSVAL_NULL; break; case QNAME_LOCALNAME: *vp = STRING_TO_JSVAL(qn->localName); break; } return JS_TRUE;}static voidqname_finalize(JSContext *cx, JSObject *obj){ JSXMLQName *qn; qn = (JSXMLQName *) JS_GetPrivate(cx, obj); if (!qn) return; JS_ASSERT(qn->object == obj); qn->object = NULL; UNMETER(xml_stats.liveqnameobj);}static voidanyname_finalize(JSContext* cx, JSObject* obj){ JSRuntime *rt; /* Make sure the next call to js_GetAnyName doesn't try to use obj. */ rt = cx->runtime; if (rt->anynameObject == obj) rt->anynameObject = NULL; qname_finalize(cx, obj);}static uint32qname_mark(JSContext *cx, JSObject *obj, void *arg){ JSXMLQName *qn; qn = (JSXMLQName *) JS_GetPrivate(cx, obj); GC_MARK(cx, qn, "private"); return 0;}static JSBoolqname_identity(JSXMLQName *qna, JSXMLQName *qnb){ if (!qna->uri ^ !qnb->uri) return JS_FALSE; if (qna->uri && !js_EqualStrings(qna->uri, qnb->uri)) return JS_FALSE; return js_EqualStrings(qna->localName, qnb->localName);}static JSBoolqname_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp){ JSXMLQName *qn, *qn2; JSObject *obj2; qn = (JSXMLQName *) JS_GetPrivate(cx, obj); JS_ASSERT(JSVAL_IS_OBJECT(v)); obj2 = JSVAL_TO_OBJECT(v); if (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_QNameClass.base) { *bp = JS_FALSE; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -