File indexing completed on 2024-05-12 15:43:26

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
0004  *  Copyright (C) 2003 Apple Computer, Inc.
0005  *
0006  *  This library is free software; you can redistribute it and/or
0007  *  modify it under the terms of the GNU Library General Public
0008  *  License as published by the Free Software Foundation; either
0009  *  version 2 of the License, or (at your option) any later version.
0010  *
0011  *  This library is distributed in the hope that it will be useful,
0012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  *  Library General Public License for more details.
0015  *
0016  *  You should have received a copy of the GNU Library General Public License
0017  *  along with this library; see the file COPYING.LIB.  If not, write to
0018  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  *  Boston, MA 02110-1301, USA.
0020  *
0021  */
0022 
0023 #ifndef KJS_LIST_H
0024 #define KJS_LIST_H
0025 
0026 #include "value.h"
0027 #include "LocalStorage.h"
0028 
0029 namespace KJS
0030 {
0031 
0032 const int inlineListValuesSize = 5;
0033 
0034 struct ListImpBase {
0035     int size;
0036     int refCount;
0037     LocalStorageEntry *data; // points either to inline or out-of-line buffer
0038 };
0039 
0040 class ListIterator;
0041 
0042 /**
0043  * @short Native list type.
0044  *
0045  * List is a native ECMAScript type. List values are only used for
0046  * intermediate results of expression evaluation and cannot be stored
0047  * as properties of objects.
0048  *
0049  * The list is explicitly shared. Note that while copyTail() returns a
0050  * copy of the list the referenced objects are still shared.
0051  */
0052 class KJS_EXPORT List
0053 {
0054 public:
0055     List();
0056     ~List()
0057     {
0058         deref();
0059     }
0060 
0061     List(const List &b) : _impBase(b._impBase)
0062     {
0063         ++_impBase->refCount;
0064     }
0065     List &operator=(const List &);
0066 
0067     /**
0068      * Append an object to the end of the list.
0069      *
0070      * @param val Pointer to object.
0071      */
0072     void append(JSValue *val);
0073 
0074     /**
0075      * Remove all elements from the list.
0076      */
0077     void clear()
0078     {
0079         _impBase->size = 0;
0080     }
0081 
0082     /*
0083      * Resets this List to point to the default empty list
0084      */
0085     void reset()
0086     {
0087         deref();
0088         ++(_impBase = empty()._impBase)->refCount;
0089     }
0090 
0091     /**
0092      * Make a copy of the list
0093      */
0094     List copy() const;
0095 
0096     /**
0097      * Make a copy of the list, omitting the first element.
0098      */
0099     List copyTail() const;
0100 
0101     /**
0102      * @return true if the list is empty. false otherwise.
0103      */
0104     bool isEmpty() const
0105     {
0106         return _impBase->size == 0;
0107     }
0108 
0109     /**
0110      * @return the current size of the list.
0111      */
0112     int size() const
0113     {
0114         return _impBase->size;
0115     }
0116 
0117     /**
0118      * @return A KJS::ListIterator pointing to the first element.
0119      */
0120     ListIterator begin() const;
0121 
0122     /**
0123      * @return A KJS::ListIterator pointing to the last element.
0124      */
0125     ListIterator end() const;
0126 
0127     /**
0128      * Retrieve an element at an indexed position.
0129      *
0130      * @param i List index.
0131      * @return Return the element at position i. KJS::Undefined if the
0132      * index is out of range.
0133      */
0134     JSValue *at(int i) const;
0135 
0136     // As above but omits the range change
0137     JSValue *atUnchecked(int i) const
0138     {
0139         return _impBase->data[i].val.valueVal;
0140     }
0141 
0142     /**
0143      * Equivalent to at.
0144      */
0145     JSValue *operator[](int i) const
0146     {
0147         return at(i);
0148     }
0149 
0150     /**
0151      * Returns a pointer to a static instance of an empty list. Useful if a
0152      * function has a KJS::List parameter.
0153      */
0154     static const List &empty();
0155 
0156     static void markProtectedLists();
0157 private:
0158     /**
0159      * Copy all elements from the second list here
0160      */
0161     void copyFrom(const List &other);
0162 
0163     void appendSlowCase(JSValue *val);
0164 
0165     ListImpBase *_impBase;
0166 
0167     void deref()
0168     {
0169         if (--_impBase->refCount == 0) {
0170             release();
0171         }
0172     }
0173 
0174     void release();
0175 };
0176 
0177 inline JSValue *List::at(int i) const
0178 {
0179     if (i < _impBase->size) {
0180         return _impBase->data[i].val.valueVal;
0181     } else {
0182         return jsUndefined();
0183     }
0184 }
0185 
0186 inline void List::append(JSValue *val)
0187 {
0188     int size = _impBase->size;
0189     int newSize = size + 1;
0190     if (newSize < inlineListValuesSize) {
0191         // Can just write to the inline buffer
0192         _impBase->data[size].val.valueVal = val;
0193         _impBase->size = newSize;
0194     } else {
0195         appendSlowCase(val);
0196     }
0197 }
0198 
0199 /**
0200  * @short Iterator for KJS::List objects.
0201  */
0202 class ListIterator
0203 {
0204 public:
0205     /**
0206      * Construct an iterator that points to the first element of the list.
0207      * @param l The list the iterator will operate on.
0208      */
0209     ListIterator(const List &l) : _list(&l), _i(0) { }
0210     ListIterator(const List &l, int index) : _list(&l), _i(index) { }
0211     /**
0212      * Dereference the iterator.
0213      * @return A pointer to the element the iterator operates on.
0214      */
0215     JSValue *operator->() const
0216     {
0217         return _list->at(_i);
0218     }
0219     JSValue *operator*() const
0220     {
0221         return _list->at(_i);
0222     }
0223     /**
0224      * Prefix increment operator.
0225      * @return The element after the increment.
0226      */
0227     JSValue *operator++()
0228     {
0229         return _list->at(++_i);
0230     }
0231     /**
0232      * Postfix increment operator.
0233      */
0234     JSValue *operator++(int)
0235     {
0236         return _list->at(_i++);
0237     }
0238     /**
0239      * Prefix decrement operator.
0240      */
0241     JSValue *operator--()
0242     {
0243         return _list->at(--_i);
0244     }
0245     /**
0246      * Postfix decrement operator.
0247      */
0248     JSValue *operator--(int)
0249     {
0250         return _list->at(_i--);
0251     }
0252     /**
0253      * Compare the iterator with another one.
0254      * @return True if the two iterators operate on the same list element.
0255      * False otherwise.
0256      */
0257     bool operator==(const ListIterator &it) const
0258     {
0259         return _i == it._i;
0260     }
0261     /**
0262      * Check for inequality with another iterator.
0263      * @return True if the two iterators operate on different list elements.
0264      */
0265     bool operator!=(const ListIterator &it) const
0266     {
0267         return _i != it._i;
0268     }
0269 
0270 private:
0271     const List *_list;
0272     int _i;
0273 };
0274 
0275 inline ListIterator List::begin() const
0276 {
0277     return ListIterator(*this);
0278 }
0279 inline ListIterator List::end() const
0280 {
0281     return ListIterator(*this, size());
0282 }
0283 
0284 } // namespace KJS
0285 
0286 #endif // KJS_LIST_H
0287