/* * This file is part of the KDE libraries * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef KJS_LIST_H #define KJS_LIST_H #include "value.h" namespace KJS { struct ListImpBase { int size; int refCount; int valueRefCount; // FIXME: Get rid of this. }; class ListIterator; /** * @short Native list type. * * List is a native ECMAScript type. List values are only used for * intermediate results of expression evaluation and cannot be stored * as properties of objects. * * The list is explicitly shared. Note that while copyTail() returns a * copy of the list the referenced objects are still shared. */ class List { public: List(); ~List() { deref(); } List(const List &b) : _impBase(b._impBase) { ++_impBase->refCount; ++_impBase->valueRefCount; } List &operator=(const List &); /** * Append an object to the end of the list. * * @param val Pointer to object. */ void append(JSValue *val); /** * Remove all elements from the list. */ void clear(); void reset() { deref(); ++(_impBase = empty()._impBase)->refCount; } /** * Make a copy of the list */ List copy() const; /** * Copy all elements from the second list here */ void copyFrom(const List& other); /** * Make a copy of the list, omitting the first element. */ List copyTail() const; /** * @return true if the list is empty. false otherwise. */ bool isEmpty() const { return _impBase->size == 0; } /** * @return the current size of the list. */ int size() const { return _impBase->size; } /** * @return A KJS::ListIterator pointing to the first element. */ ListIterator begin() const; /** * @return A KJS::ListIterator pointing to the last element. */ ListIterator end() const; /** * Retrieve an element at an indexed position. If you want to iterate * trough the whole list using KJS::ListIterator will be faster. * * @param i List index. * @return Return the element at position i. KJS::Undefined if the * index is out of range. */ JSValue *at(int i) const; /** * Equivalent to at. */ JSValue *operator[](int i) const { return at(i); } /** * Returns a pointer to a static instance of an empty list. Useful if a * function has a KJS::List parameter. */ static const List &empty(); static void markProtectedLists(); private: ListImpBase *_impBase; void deref() { --_impBase->valueRefCount; if (--_impBase->refCount == 0) release(); } void release(); void markValues(); }; /** * @short Iterator for KJS::List objects. */ class ListIterator { public: /** * Construct an iterator that points to the first element of the list. * @param l The list the iterator will operate on. */ ListIterator(const List &l) : _list(&l), _i(0) { } ListIterator(const List &l, int index) : _list(&l), _i(index) { } /** * Dereference the iterator. * @return A pointer to the element the iterator operates on. */ JSValue *operator->() const { return _list->at(_i); } JSValue *operator*() const { return _list->at(_i); } /** * Prefix increment operator. * @return The element after the increment. */ JSValue *operator++() { return _list->at(++_i); } /** * Postfix increment operator. */ JSValue *operator++(int) { return _list->at(_i++); } /** * Prefix decrement operator. */ JSValue *operator--() { return _list->at(--_i); } /** * Postfix decrement operator. */ JSValue *operator--(int) { return _list->at(_i--); } /** * Compare the iterator with another one. * @return True if the two iterators operate on the same list element. * False otherwise. */ bool operator==(const ListIterator &it) const { return _i == it._i; } /** * Check for inequality with another iterator. * @return True if the two iterators operate on different list elements. */ bool operator!=(const ListIterator &it) const { return _i != it._i; } private: const List *_list; int _i; }; inline ListIterator List::begin() const { return ListIterator(*this); } inline ListIterator List::end() const { return ListIterator(*this, size()); } } // namespace KJS #endif // KJS_LIST_H