1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef __avmplus_E4XNode__
41 #define __avmplus_E4XNode__
44 // E4X 9.1.1 Internal Properties and Methods
50 // Delete (overrides Object version)
51 // Get (overrides Object version)
52 // HasProperty (overrides Object version)
53 // Put (overrides Object version)
54 // DeleteByIndex (PropertyName)
57 // Descendants (PropertyName)
59 // Insert (PropertyName, Value)
60 // Replace (PropertyName, Value)
61 // AddInScopeNamespace (Namespace)
63 // These are static objects on the XML type
64 // E4X: The XML constructor has the following properties
66 // XML.ignoreProcessingInstructions
67 // XML.ignoreWhitespace
71 // XML.setSettings ([settings])
72 // XML.defaultSettings()
74 // XML.prototype.constructor ??
75 // XML.prototype.addNamespace
76 // XML.prototype.appendChild
77 // XML.prototype.attribute
78 // XML.prototype.attributes
79 // XML.prototype.child
80 // XML.prototype.childIndex
81 // XML.prototype.children
82 // XML.prototype.comments
83 // XML.prototype.contains
85 // XML.prototype.descendants
86 // XML.prototype.elements
87 // XML.prototype.hasOwnProperty
88 // XML.prototype.hasComplexContent
89 // XML.prototype.hasSimpleContent
90 // XML.prototype.inScopeNamespaces
91 // XML.prototype.insertChildAfter
92 // XML.prototype.insertChildBefore
93 // XML.prototype.length
94 // XML.prototype.localName
96 // XML.prototype.namespace
97 // XML.prototype.namespaceDeclarations
98 // XML.prototype.nodeKind
99 // XML.prototype.normalize
100 // XML.prototype.parent
101 // XML.prototype.processingInstructions
102 // XML.prototype.prependChild
103 // XML.prototype.propertyIsEnumerable
104 // XML.prototype.removeNamespace
105 // XML.prototype.replace
106 // XML.prototype.setChildren
107 // XML.prototype.setLocalName
108 // XML.prototype.setName
109 // XML.prototype.setNamespace
110 // XML.prototype.text
111 // XML.prototype.toString
112 // XML.prototype.toXMLString
113 // XML.prototype.valueOf
117 class GC_CPP_EXACT(E4XNodeAux
, MMgc::GCTraceableObject
)
119 friend class E4XNode
;
120 friend class ElementE4XNode
;
123 E4XNodeAux(Stringp s
, Namespace
* ns
, FunctionObject
* notify
= NULL
);
126 REALLY_INLINE
static E4XNodeAux
* create(MMgc::GC
* gc
, Stringp name
, Namespace
*ns
, FunctionObject
* notify
= NULL
)
128 return new (gc
, MMgc::kExact
) E4XNodeAux (name
, ns
, notify
);
132 uint64_t bytesUsed() const;
136 GC_DATA_BEGIN(E4XNodeAux
)
138 DRCWB(Stringp
) GC_POINTER(m_name
);
139 DRCWB(Namespace
*) GC_POINTER(m_ns
);
141 /** callback on changes to children, attribute, name or namespace */
142 DRCWB(FunctionObject
*) GC_POINTER(m_notification
);
144 GC_DATA_END(E4XNodeAux
)
147 ///////////////////////////////////////////////////
148 ///////////////////////////////////////////////////
150 * E4XNode is the C++ implementation of the XML class
151 * in the E4X Specification.
153 // Currently this is 12-bytes in size (4 bytes wasted by GC)
154 // Element nodes are 24 bytes
155 // All other nodes are 16 bytes
156 class GC_CPP_EXACT(E4XNode
, MMgc::GCTraceableObject
)
158 friend class ElementE4XNode
;
161 GC_DATA_BEGIN(E4XNode
)
163 /** Either null or an E4XNode, valid for all node types */
164 DWB(E4XNode
*) GC_POINTER(m_parent
);
166 // If this is a simple name with no namespace or notification function,
167 // we just have a string pointer. Otherwise, we're a E4XNodeAux value
168 // containing a name + namespace as well as a notification function.
171 uintptr_t GC_POINTER(m_nameOrAux
);
177 E4XNode(E4XNode
* parent
) : m_parent(parent
), m_nameOrAux(0) { }
181 typedef GCList
<E4XNode
> E4XNodeList
;
182 typedef HeapList
<E4XNodeList
> HeapE4XNodeList
;
185 bool getQName (Multiname
*mn
, Namespacep publicNS
) const;
186 void setQName (AvmCore
*core
, Stringp name
, Namespace
*ns
= 0);
187 void setQName (AvmCore
*core
, const Multiname
*mn
);
189 virtual Stringp
getValue() const = 0;
190 virtual void setValue (String
*s
) = 0;
192 E4XNode
* getParent() const { return m_parent
; }
193 void setParent(E4XNode
* n
) { m_parent
= n
; }
195 // Not used as bit fields (only one bit at a time can be set) but
196 // used for fast multi-type compares.
202 kCDATA
= 0x0008, // same as text but no string conversion on output
204 kProcessingInstruction
= 0x0020,
208 virtual int getClass() const = 0;
210 virtual uint32_t numAttributes() const { return 0; }
211 virtual HeapE4XNodeList
* getAttributes() const { return 0; }
212 virtual E4XNode
*getAttribute(uint32_t /*index*/) const { return NULL
; }
214 virtual uint32_t numNamespaces() const { return 0; }
215 virtual HeapNamespaceList
* getNamespaces() const { return 0; }
217 virtual uint32_t numChildren() const { return 0; }
218 virtual E4XNode
*_getAt(uint32_t /*i*/) const { return 0; }
220 virtual void clearChildren() {}
221 virtual void setChildAt (uint32_t /*i*/, E4XNode
* /*x*/) {}
222 virtual void insertChild (uint32_t /*i*/, E4XNode
* /*x*/) {}
223 virtual void removeChild (uint32_t /*i*/) {}
224 virtual void convertToE4XNodeList() {}
226 bool hasSimpleContent() const;
227 bool hasComplexContent() const;
228 int32_t childIndex() const;
229 String
* nodeKind(Toplevel
* toplevel
) const;
231 virtual void addAttribute (E4XNode
*x
);
233 // Should this silently fail or assert?
234 virtual void setNotification(AvmCore
* /*core*/, FunctionObject
* /*f*/, Namespacep
/*publicNS*/) { return; }
235 virtual FunctionObject
* getNotification() const { return NULL
; }
237 // The following routines are E4X support routines
239 // Private functions not exposed to AS
240 // DeleteByIndex (PropertyName)
243 // Descendants (PropertyName)
245 // Insert (PropertyName, Value)
246 // Replace (PropertyName, Value)
247 // AddInScopeNamespace (Namespace)
249 // Corresponds to [[Length]] in the docs
250 virtual uint32_t _length() const { return 0; }
252 bool _equals(Toplevel
* toplevel
, AvmCore
*core
, E4XNode
*value
) const;
254 void _deleteByIndex (uint32_t entry
);
255 E4XNode
*_deepCopy (AvmCore
*core
, Toplevel
*toplevel
, Namespacep publicNS
) const;
256 virtual void _insert (AvmCore
*core
, Toplevel
*toplevel
, uint32_t entry
, Atom value
);
257 virtual E4XNode
* _replace (AvmCore
*core
, Toplevel
*toplevel
, uint32_t entry
, Atom value
, Atom pastValue
= 0);
258 virtual void _addInScopeNamespace (AvmCore
*core
, Namespace
*ns
, Namespacep publicNS
);
259 virtual void _append (E4XNode
* /*childNode*/) { AvmAssert(0); }
260 // Extract a namespace from a tag name, and return the new tag name in tagName
261 Namespace
*FindNamespace(AvmCore
*core
, Toplevel
*toplevel
, Stringp
& tagName
, bool bAttribute
);
262 int FindMatchingNamespace(AvmCore
*core
, Namespace
*ns
);
264 void BuildInScopeNamespaceList(AvmCore
*core
, NamespaceList
& list
) const;
267 MMgc::GC
*gc() const { return MMgc::GC::GetGC(this); }
271 uint64_t bytesUsed() const;
274 // Internal helper function called by bytesUsed(), which calculates how much
275 // memory is used from this node on down to the bottom of the tree of E4XNodes;
276 // will not look "up" the tree at m_parent.
277 virtual uint64_t bytesUsedDown() const;
281 class GC_CPP_EXACT(TextE4XNode
, E4XNode
)
283 GC_DATA_BEGIN(TextE4XNode
)
284 DRCWB(Stringp
) GC_POINTER(m_value
);
285 GC_DATA_END(TextE4XNode
)
287 TextE4XNode (E4XNode
*parent
, String
*value
);
289 REALLY_INLINE
static TextE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
, String
*value
)
291 return new (gc
, MMgc::kExact
) TextE4XNode(parent
, value
);
294 int getClass() const { return kText
; }
295 Stringp
getValue() const { return m_value
; }
296 void setValue (String
*s
) { m_value
= s
; }
300 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value
->bytesUsed(); }
304 class GC_CPP_EXACT(CommentE4XNode
, E4XNode
)
306 GC_DATA_BEGIN(CommentE4XNode
)
307 DRCWB(Stringp
) GC_POINTER(m_value
);
308 GC_DATA_END(CommentE4XNode
)
310 CommentE4XNode (E4XNode
*parent
, String
*value
);
312 REALLY_INLINE
static CommentE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
, String
*value
)
314 return new (gc
, MMgc::kExact
) CommentE4XNode(parent
, value
);
317 int getClass() const { return kComment
; }
318 Stringp
getValue() const { return m_value
; }
319 void setValue (String
*s
) { m_value
= s
; }
323 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value
->bytesUsed(); }
327 class GC_CPP_EXACT(AttributeE4XNode
, E4XNode
)
329 GC_DATA_BEGIN(AttributeE4XNode
)
330 DRCWB(Stringp
) GC_POINTER(m_value
);
331 GC_DATA_END(AttributeE4XNode
)
333 AttributeE4XNode (E4XNode
*parent
, String
*value
);
336 REALLY_INLINE
static AttributeE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
, String
*value
)
338 return new (gc
, MMgc::kExact
) AttributeE4XNode(parent
, value
);
341 int getClass() const { return kAttribute
; }
342 Stringp
getValue() const { return m_value
; }
343 void setValue (String
*s
) { m_value
= s
; }
347 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value
->bytesUsed(); }
351 class GC_CPP_EXACT(CDATAE4XNode
, E4XNode
)
353 GC_DATA_BEGIN(CDATAE4XNode
)
354 DRCWB(Stringp
) GC_POINTER(m_value
);
355 GC_DATA_END(CDATAE4XNode
)
357 CDATAE4XNode (E4XNode
*parent
, String
*value
);
359 REALLY_INLINE
static CDATAE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
, String
*value
)
361 return new (gc
, MMgc::kExact
) CDATAE4XNode(parent
, value
);
364 int getClass() const { return kCDATA
; }
365 Stringp
getValue() const { return m_value
; }
366 void setValue (String
*s
) { m_value
= s
; }
370 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value
->bytesUsed(); }
374 class GC_CPP_EXACT(PIE4XNode
, E4XNode
)
376 GC_DATA_BEGIN(PIE4XNode
)
377 DRCWB(Stringp
) GC_POINTER(m_value
); // only when m_class != kElement
378 GC_DATA_END(PIE4XNode
)
380 PIE4XNode (E4XNode
*parent
, String
*value
);
382 REALLY_INLINE
static PIE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
, String
*value
)
384 return new (gc
, MMgc::kExact
) PIE4XNode(parent
, value
);
387 int getClass() const { return kProcessingInstruction
; }
388 Stringp
getValue() const { return m_value
; }
389 void setValue (String
*s
) { m_value
= s
; }
393 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value
->bytesUsed(); }
397 // Currently this is 24-bytes in size
398 class GC_CPP_EXACT(ElementE4XNode
, E4XNode
)
400 GC_DATA_BEGIN(ElementE4XNode
)
402 DWB(HeapE4XNodeList
*) GC_POINTER(m_attributes
);
404 DWB(HeapNamespaceList
*) GC_POINTER(m_namespaces
);
406 // If the low bit of this integer is set, this value points directly
407 // to a single child (one E4XNode *). If there are multiple children,
408 // this points to a HeapE4XNodeList
409 DWB(uintptr_t) GC_POINTER(m_children
);
410 #define SINGLECHILDBIT 0x1
412 GC_DATA_END(ElementE4XNode
)
414 friend class E4XNode
;
416 ElementE4XNode (E4XNode
*parent
);
418 REALLY_INLINE
static ElementE4XNode
* create(MMgc::GC
* gc
, E4XNode
*parent
)
420 return new (gc
, MMgc::kExact
) ElementE4XNode(parent
);
423 int getClass() const { return kElement
; }
425 uint32_t numAttributes() const;
426 HeapE4XNodeList
* getAttributes() const;
427 E4XNode
*getAttribute(uint32_t index
) const;
428 void addAttribute (E4XNode
*x
);
430 uint32_t numNamespaces() const;
431 HeapNamespaceList
* getNamespaces() const;
433 uint32_t numChildren() const;
435 void clearChildren();
436 void setChildAt (uint32_t i
, E4XNode
*x
);
437 #define SINGLECHILDBIT 0x1
438 void insertChild (uint32_t i
, E4XNode
*x
);
439 void removeChild (uint32_t i
);
440 void convertToE4XNodeList();
442 Stringp
getValue() const { return 0; }
443 void setValue (String
*s
) { (void)s
; AvmAssert(s
== 0); }
445 void setNotification(AvmCore
* core
, FunctionObject
* f
, Namespacep publicNS
);
446 FunctionObject
* getNotification() const;
448 // E4X support routines below
449 uint32_t _length() const { return numChildren(); }
450 E4XNode
*_getAt(uint32_t i
) const;
452 void _append (E4XNode
*childNode
);
454 void _addInScopeNamespace (AvmCore
*core
, Namespace
*ns
, Namespacep publicNS
);
455 void _insert (AvmCore
*core
, Toplevel
*toplevel
, uint32_t entry
, Atom value
);
456 E4XNode
* _replace (AvmCore
*core
, Toplevel
*toplevel
, uint32_t entry
, Atom value
, Atom pastValue
= 0);
458 void CopyAttributesAndNamespaces(AvmCore
*core
, Toplevel
*toplevel
, XMLTag
& tag
, Namespacep publicNS
);
462 virtual uint64_t bytesUsedDown() const;
466 #endif /* __avmplus_E4XNode__ */