1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4 * Copyright (C) 2003 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef KJS_LIST_H
24#define KJS_LIST_H
25
26#include "value.h"
27#include "LocalStorage.h"
28
29namespace KJS {
30
31 const int inlineListValuesSize = 5;
32
33 struct ListImpBase {
34 int size;
35 int refCount;
36 LocalStorageEntry* data; // points either to inline or out-of-line buffer
37 };
38
39 class ListIterator;
40
41 /**
42 * @short Native list type.
43 *
44 * List is a native ECMAScript type. List values are only used for
45 * intermediate results of expression evaluation and cannot be stored
46 * as properties of objects.
47 *
48 * The list is explicitly shared. Note that while copyTail() returns a
49 * copy of the list the referenced objects are still shared.
50 */
51 class KJS_EXPORT List {
52 public:
53 List();
54 ~List() { deref(); }
55
56 List(const List &b) : _impBase(b._impBase) { ++_impBase->refCount; }
57 List &operator=(const List &);
58
59 /**
60 * Append an object to the end of the list.
61 *
62 * @param val Pointer to object.
63 */
64 void append(JSValue *val);
65
66 /**
67 * Remove all elements from the list.
68 */
69 void clear() { _impBase->size = 0; }
70
71 /*
72 * Resets this List to point to the default empty list
73 */
74 void reset() { deref(); ++(_impBase = empty()._impBase)->refCount; }
75
76 /**
77 * Make a copy of the list
78 */
79 List copy() const;
80
81 /**
82 * Make a copy of the list, omitting the first element.
83 */
84 List copyTail() const;
85
86 /**
87 * @return true if the list is empty. false otherwise.
88 */
89 bool isEmpty() const { return _impBase->size == 0; }
90
91 /**
92 * @return the current size of the list.
93 */
94 int size() const { return _impBase->size; }
95
96 /**
97 * @return A KJS::ListIterator pointing to the first element.
98 */
99 ListIterator begin() const;
100
101 /**
102 * @return A KJS::ListIterator pointing to the last element.
103 */
104 ListIterator end() const;
105
106 /**
107 * Retrieve an element at an indexed position.
108 *
109 * @param i List index.
110 * @return Return the element at position i. KJS::Undefined if the
111 * index is out of range.
112 */
113 JSValue *at(int i) const;
114
115 // As above but omits the range change
116 JSValue* atUnchecked(int i) const { return _impBase->data[i].val.valueVal; }
117
118 /**
119 * Equivalent to at.
120 */
121 JSValue *operator[](int i) const { return at(i); }
122
123 /**
124 * Returns a pointer to a static instance of an empty list. Useful if a
125 * function has a KJS::List parameter.
126 */
127 static const List &empty();
128
129 static void markProtectedLists();
130 private:
131 /**
132 * Copy all elements from the second list here
133 */
134 void copyFrom(const List& other);
135
136 void appendSlowCase(JSValue* val);
137
138 ListImpBase *_impBase;
139
140 void deref() { if (--_impBase->refCount == 0) release(); }
141
142 void release();
143 };
144
145 inline JSValue* List::at(int i) const {
146 if (i < _impBase->size)
147 return _impBase->data[i].val.valueVal;
148 else
149 return jsUndefined();
150 }
151
152 inline void List::append(JSValue *val) {
153 int size = _impBase->size;
154 int newSize = size + 1;
155 if (newSize < inlineListValuesSize) {
156 // Can just write to the inline buffer
157 _impBase->data[size].val.valueVal = val;
158 _impBase->size = newSize;
159 } else {
160 appendSlowCase(val);
161 }
162 }
163
164 /**
165 * @short Iterator for KJS::List objects.
166 */
167 class ListIterator {
168 public:
169 /**
170 * Construct an iterator that points to the first element of the list.
171 * @param l The list the iterator will operate on.
172 */
173 ListIterator(const List &l) : _list(&l), _i(0) { }
174 ListIterator(const List &l, int index) : _list(&l), _i(index) { }
175 /**
176 * Dereference the iterator.
177 * @return A pointer to the element the iterator operates on.
178 */
179 JSValue *operator->() const { return _list->at(_i); }
180 JSValue *operator*() const { return _list->at(_i); }
181 /**
182 * Prefix increment operator.
183 * @return The element after the increment.
184 */
185 JSValue *operator++() { return _list->at(++_i); }
186 /**
187 * Postfix increment operator.
188 */
189 JSValue *operator++(int) { return _list->at(_i++); }
190 /**
191 * Prefix decrement operator.
192 */
193 JSValue *operator--() { return _list->at(--_i); }
194 /**
195 * Postfix decrement operator.
196 */
197 JSValue *operator--(int) { return _list->at(_i--); }
198 /**
199 * Compare the iterator with another one.
200 * @return True if the two iterators operate on the same list element.
201 * False otherwise.
202 */
203 bool operator==(const ListIterator &it) const { return _i == it._i; }
204 /**
205 * Check for inequality with another iterator.
206 * @return True if the two iterators operate on different list elements.
207 */
208 bool operator!=(const ListIterator &it) const { return _i != it._i; }
209
210 private:
211 const List *_list;
212 int _i;
213 };
214
215 inline ListIterator List::begin() const { return ListIterator(*this); }
216 inline ListIterator List::end() const { return ListIterator(*this, size()); }
217
218} // namespace KJS
219
220#endif // KJS_LIST_H
221
222// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;
223