util/src/script/api/qscriptvalueiterator.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtScript module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
       
    10 ** GNU Lesser General Public License Usage
       
    11 ** This file may be used under the terms of the GNU Lesser
       
    12 ** General Public License version 2.1 as published by the Free Software
       
    13 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    14 ** packaging of this file.  Please review the following information to
       
    15 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    16 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    17 **
       
    18 ** If you have questions regarding the use of this file, please contact
       
    19 ** Nokia at qt-info@nokia.com.
       
    20 ** $QT_END_LICENSE$
       
    21 **
       
    22 ****************************************************************************/
       
    23 
       
    24 #include "config.h"
       
    25 #include "qscriptvalueiterator.h"
       
    26 
       
    27 #include "qscriptstring.h"
       
    28 #include "qscriptengine.h"
       
    29 #include "qscriptengine_p.h"
       
    30 #include "qscriptvalue_p.h"
       
    31 #include "qlinkedlist.h"
       
    32 
       
    33 
       
    34 #include "JSObject.h"
       
    35 #include "PropertyNameArray.h"
       
    36 #include "JSArray.h"
       
    37 #include "JSFunction.h"
       
    38 
       
    39 QT_BEGIN_NAMESPACE
       
    40 
       
    41 /*!
       
    42   \since 4.3
       
    43   \class QScriptValueIterator
       
    44 
       
    45   \brief The QScriptValueIterator class provides a Java-style iterator for QScriptValue.
       
    46 
       
    47   \ingroup script
       
    48 
       
    49 
       
    50   The QScriptValueIterator constructor takes a QScriptValue as
       
    51   argument.  After construction, the iterator is located at the very
       
    52   beginning of the sequence of properties. Here's how to iterate over
       
    53   all the properties of a QScriptValue:
       
    54 
       
    55   \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0
       
    56 
       
    57   The next() advances the iterator. The name(), value() and flags()
       
    58   functions return the name, value and flags of the last item that was
       
    59   jumped over.
       
    60 
       
    61   If you want to remove properties as you iterate over the
       
    62   QScriptValue, use remove(). If you want to modify the value of a
       
    63   property, use setValue().
       
    64 
       
    65   Note that QScriptValueIterator only iterates over the QScriptValue's
       
    66   own properties; i.e. it does not follow the prototype chain. You can
       
    67   use a loop like this to follow the prototype chain:
       
    68 
       
    69   \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1
       
    70 
       
    71   Note that QScriptValueIterator will not automatically skip over
       
    72   properties that have the QScriptValue::SkipInEnumeration flag set;
       
    73   that flag only affects iteration in script code.  If you want, you
       
    74   can skip over such properties with code like the following:
       
    75 
       
    76   \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2
       
    77 
       
    78   \sa QScriptValue::property()
       
    79 */
       
    80 
       
    81 class QScriptValueIteratorPrivate
       
    82 {
       
    83 public:
       
    84     QScriptValueIteratorPrivate()
       
    85         : initialized(false)
       
    86     {}
       
    87     void ensureInitialized()
       
    88     {
       
    89         if (initialized)
       
    90             return;
       
    91         QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(object.engine());
       
    92         JSC::ExecState *exec = eng_p->globalExec();
       
    93         JSC::PropertyNameArray propertyNamesArray(exec);
       
    94         propertyNamesArray.setShouldCache(false);
       
    95         JSC::asObject(QScriptValuePrivate::get(object)->jscValue)->getOwnPropertyNames(exec, propertyNamesArray, /*includeNonEnumerable=*/true);
       
    96 
       
    97         JSC::PropertyNameArray::const_iterator propertyNamesIt = propertyNamesArray.begin();
       
    98         for(; propertyNamesIt != propertyNamesArray.end(); ++propertyNamesIt) {
       
    99             propertyNames.append(propertyNamesIt->ustring());
       
   100         }
       
   101         it = propertyNames.begin();
       
   102         initialized = true;
       
   103     }
       
   104 
       
   105     QScriptValue object;
       
   106     QLinkedList<JSC::UString> propertyNames;
       
   107     QLinkedList<JSC::UString>::iterator it;
       
   108     QLinkedList<JSC::UString>::iterator current;
       
   109     bool initialized;
       
   110 };
       
   111 
       
   112 /*!
       
   113   Constructs an iterator for traversing \a object. The iterator is
       
   114   set to be at the front of the sequence of properties (before the
       
   115   first property).
       
   116 */
       
   117 QScriptValueIterator::QScriptValueIterator(const QScriptValue &object)
       
   118     : d_ptr(0)
       
   119 {
       
   120     if (object.isObject()) {
       
   121         d_ptr.reset(new QScriptValueIteratorPrivate());
       
   122         d_ptr->object = object;
       
   123     }
       
   124 }
       
   125 
       
   126 /*!
       
   127   Destroys the iterator.
       
   128 */
       
   129 QScriptValueIterator::~QScriptValueIterator()
       
   130 {
       
   131 }
       
   132 
       
   133 /*!
       
   134   Returns true if there is at least one item ahead of the iterator
       
   135   (i.e. the iterator is \e not at the back of the property sequence);
       
   136   otherwise returns false.
       
   137 
       
   138   \sa next(), hasPrevious()
       
   139 */
       
   140 bool QScriptValueIterator::hasNext() const
       
   141 {
       
   142     Q_D(const QScriptValueIterator);
       
   143     if (!d)
       
   144         return false;
       
   145 
       
   146     const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized();
       
   147     return d->it != d->propertyNames.end();
       
   148 }
       
   149 
       
   150 /*!
       
   151   Advances the iterator by one position.
       
   152 
       
   153   Calling this function on an iterator located at the back of the
       
   154   container leads to undefined results.
       
   155 
       
   156   \sa hasNext(), previous(), name()
       
   157 */
       
   158 void QScriptValueIterator::next()
       
   159 {
       
   160     Q_D(QScriptValueIterator);
       
   161     if (!d)
       
   162         return;
       
   163     d->ensureInitialized();
       
   164 
       
   165     d->current = d->it;
       
   166     ++(d->it);
       
   167 }
       
   168 
       
   169 /*!
       
   170   Returns true if there is at least one item behind the iterator
       
   171   (i.e. the iterator is \e not at the front of the property sequence);
       
   172   otherwise returns false.
       
   173 
       
   174   \sa previous(), hasNext()
       
   175 */
       
   176 bool QScriptValueIterator::hasPrevious() const
       
   177 {
       
   178     Q_D(const QScriptValueIterator);
       
   179     if (!d)
       
   180         return false;
       
   181 
       
   182     const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized();
       
   183     return d->it != d->propertyNames.begin();
       
   184 }
       
   185 
       
   186 /*!
       
   187   Moves the iterator back by one position.
       
   188 
       
   189   Calling this function on an iterator located at the front of the
       
   190   container leads to undefined results.
       
   191 
       
   192   \sa hasPrevious(), next(), name()
       
   193 */
       
   194 void QScriptValueIterator::previous()
       
   195 {
       
   196     Q_D(QScriptValueIterator);
       
   197     if (!d)
       
   198         return;
       
   199     d->ensureInitialized();
       
   200     --(d->it);
       
   201     d->current = d->it;
       
   202 }
       
   203 
       
   204 /*!
       
   205   Moves the iterator to the front of the QScriptValue (before the
       
   206   first property).
       
   207 
       
   208   \sa toBack(), next()
       
   209 */
       
   210 void QScriptValueIterator::toFront()
       
   211 {
       
   212     Q_D(QScriptValueIterator);
       
   213     if (!d)
       
   214         return;
       
   215     d->ensureInitialized();
       
   216     d->it = d->propertyNames.begin();
       
   217 }
       
   218 
       
   219 /*!
       
   220   Moves the iterator to the back of the QScriptValue (after the
       
   221   last property).
       
   222 
       
   223   \sa toFront(), previous()
       
   224 */
       
   225 void QScriptValueIterator::toBack()
       
   226 {
       
   227     Q_D(QScriptValueIterator);
       
   228     if (!d)
       
   229         return;
       
   230     d->ensureInitialized();
       
   231     d->it = d->propertyNames.end();
       
   232 }
       
   233 
       
   234 /*!
       
   235   Returns the name of the last property that was jumped over using
       
   236   next() or previous().
       
   237 
       
   238   \sa value(), flags()
       
   239 */
       
   240 QString QScriptValueIterator::name() const
       
   241 {
       
   242     Q_D(const QScriptValueIterator);
       
   243     if (!d || !d->initialized)
       
   244         return QString();
       
   245     return *d->current;
       
   246 }
       
   247 
       
   248 /*!
       
   249   \since 4.4
       
   250 
       
   251   Returns the name of the last property that was jumped over using
       
   252   next() or previous().
       
   253 */
       
   254 QScriptString QScriptValueIterator::scriptName() const
       
   255 {
       
   256     Q_D(const QScriptValueIterator);
       
   257     if (!d || !d->initialized)
       
   258         return QScriptString();
       
   259     return d->object.engine()->toStringHandle(name());
       
   260 }
       
   261 
       
   262 /*!
       
   263   Returns the value of the last property that was jumped over using
       
   264   next() or previous().
       
   265 
       
   266   \sa setValue(), name()
       
   267 */
       
   268 QScriptValue QScriptValueIterator::value() const
       
   269 {
       
   270     Q_D(const QScriptValueIterator);
       
   271     if (!d || !d->initialized)
       
   272         return QScriptValue();
       
   273     return d->object.property(name());
       
   274 }
       
   275 
       
   276 /*!
       
   277   Sets the \a value of the last property that was jumped over using
       
   278   next() or previous().
       
   279 
       
   280   \sa value(), name()
       
   281 */
       
   282 void QScriptValueIterator::setValue(const QScriptValue &value)
       
   283 {
       
   284     Q_D(QScriptValueIterator);
       
   285     if (!d || !d->initialized)
       
   286         return;
       
   287     d->object.setProperty(name(), value);
       
   288 }
       
   289 
       
   290 /*!
       
   291   Returns the flags of the last property that was jumped over using
       
   292   next() or previous().
       
   293 
       
   294   \sa value()
       
   295 */
       
   296 QScriptValue::PropertyFlags QScriptValueIterator::flags() const
       
   297 {
       
   298     Q_D(const QScriptValueIterator);
       
   299     if (!d || !d->initialized)
       
   300         return 0;
       
   301     return d->object.propertyFlags(name());
       
   302 }
       
   303 
       
   304 /*!
       
   305   Removes the last property that was jumped over using next()
       
   306   or previous().
       
   307 
       
   308   \sa setValue()
       
   309 */
       
   310 void QScriptValueIterator::remove()
       
   311 {
       
   312     Q_D(QScriptValueIterator);
       
   313     if (!d || !d->initialized)
       
   314         return;
       
   315     d->object.setProperty(name(), QScriptValue());
       
   316     d->propertyNames.erase(d->current);
       
   317 }
       
   318 
       
   319 /*!
       
   320   Makes the iterator operate on \a object. The iterator is set to be
       
   321   at the front of the sequence of properties (before the first
       
   322   property).
       
   323 */
       
   324 QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue &object)
       
   325 {
       
   326     d_ptr.reset();
       
   327     if (object.isObject()) {
       
   328         d_ptr.reset(new QScriptValueIteratorPrivate());
       
   329         d_ptr->object = object;
       
   330     }
       
   331     return *this;
       
   332 }
       
   333 
       
   334 QT_END_NAMESPACE