Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / core / E4XNode.h
bloba27da010ce85ea2e833facdec0d2bad5459b3933
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
14 * License.
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.
23 * Contributor(s):
24 * Adobe AS3 Team
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
45 // Name
46 // Parent
47 // Attributes
48 // InScopeNamespaces
49 // Length
50 // Delete (overrides Object version)
51 // Get (overrides Object version)
52 // HasProperty (overrides Object version)
53 // Put (overrides Object version)
54 // DeleteByIndex (PropertyName)
55 // DeepCopy
56 // ResolveValue
57 // Descendants (PropertyName)
58 // Equals (Value)
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
65 // XML.ignoreComments
66 // XML.ignoreProcessingInstructions
67 // XML.ignoreWhitespace
68 // XML.prettyPrinting
69 // XML.prettyIndent
70 // XML.settings
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
84 // XML.prototype.copy
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
95 // XML.prototype.name
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
115 namespace avmplus
117 class GC_CPP_EXACT(E4XNodeAux, MMgc::GCTraceableObject)
119 friend class E4XNode;
120 friend class ElementE4XNode;
122 private:
123 E4XNodeAux(Stringp s, Namespace* ns, FunctionObject* notify = NULL);
125 public:
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);
131 #ifdef DEBUGGER
132 uint64_t bytesUsed() const;
133 #endif
135 private:
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;
160 protected:
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.
169 // E4XNodeAux *
170 // String *
171 uintptr_t GC_POINTER(m_nameOrAux);
172 #define AUXBIT 0x1
174 GC_DATA_END(E4XNode)
176 protected:
177 E4XNode(E4XNode* parent) : m_parent(parent), m_nameOrAux(0) { }
179 public:
181 typedef GCList<E4XNode> E4XNodeList;
182 typedef HeapList<E4XNodeList> HeapE4XNodeList;
184 public:
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.
197 enum NodeTypes
199 kUnknown = 0x0001,
200 kAttribute = 0x0002,
201 kText = 0x0004,
202 kCDATA = 0x0008, // same as text but no string conversion on output
203 kComment = 0x0010,
204 kProcessingInstruction = 0x0020,
205 kElement = 0x0040
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)
241 // DeepCopy
242 // ResolveValue
243 // Descendants (PropertyName)
244 // Equals (Value)
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;
265 void dispose();
267 MMgc::GC *gc() const { return MMgc::GC::GetGC(this); }
269 #ifdef DEBUGGER
270 public:
271 uint64_t bytesUsed() const;
273 protected:
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;
278 #endif
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);
288 public:
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; }
298 #ifdef DEBUGGER
299 protected:
300 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value->bytesUsed(); }
301 #endif
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);
311 public:
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; }
321 #ifdef DEBUGGER
322 protected:
323 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value->bytesUsed(); }
324 #endif
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);
335 public:
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; }
345 #ifdef DEBUGGER
346 protected:
347 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value->bytesUsed(); }
348 #endif
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);
358 public:
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; }
368 #ifdef DEBUGGER
369 protected:
370 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value->bytesUsed(); }
371 #endif
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);
381 public:
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; }
391 #ifdef DEBUGGER
392 protected:
393 virtual uint64_t bytesUsedDown() const { return E4XNode::bytesUsedDown() + m_value->bytesUsed(); }
394 #endif
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);
417 public:
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);
460 #ifdef DEBUGGER
461 protected:
462 virtual uint64_t bytesUsedDown() const;
463 #endif
466 #endif /* __avmplus_E4XNode__ */