summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2012-01-10 11:58:31 +0100
committerLars Knoll <lars.knoll@nokia.com>2012-01-11 14:58:09 +0100
commit2e20b0abf92b2ee81a4328ae5d1ae4aaff46e189 (patch)
treef1e50437c320730da89b358731ddd7635f38329e
parent1fca88779c35a9adc848e482be2ddaca5e54a3db (diff)
Added an iterator interface to QJsonObject
Added both iterator and const_iterator and the required typedefs and methods for STL compatibility. Change-Id: Icee9a4bea45ce5499882bc83b8b62c3431b8c976 Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Denis Dzyubenko <denis.dzyubenko@nokia.com>
-rw-r--r--src/qjsonobject.cpp46
-rw-r--r--src/qjsonobject.h125
-rw-r--r--tests/auto/tst_qtjson.cpp86
3 files changed, 248 insertions, 9 deletions
diff --git a/src/qjsonobject.cpp b/src/qjsonobject.cpp
index 613d382..8c09fbe 100644
--- a/src/qjsonobject.cpp
+++ b/src/qjsonobject.cpp
@@ -170,11 +170,11 @@ QJsonValueRef QJsonObject::operator [](const QString &key)
return QJsonValueRef(this, index);
}
-void QJsonObject::insert(const QString &key, const QJsonValue &value)
+QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value)
{
if (value.t == QJsonValue::Undefined) {
remove(key);
- return;
+ return end();
}
bool latinOrIntValue;
@@ -208,6 +208,8 @@ void QJsonObject::insert(const QString &key, const QJsonValue &value)
Private::copyString((char *)(e + 1), key, latinKey);
if (valueSize)
value.copyData((char *)e + valueOffset, latinOrIntValue);
+
+ return iterator(this, pos);
}
void QJsonObject::remove(const QString &key)
@@ -279,6 +281,39 @@ bool QJsonObject::operator!=(const QJsonObject &other) const
return !(*this == other);
}
+QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
+{
+ Q_ASSERT(d && d->ref.load() == 1);
+ if (it.o != this || it.i < 0 || it.i >= (int)o->length)
+ return iterator(this, o->length);
+
+ int index = it.i;
+
+ o->removeItems(index, 1);
+ ++d->compactionCounter;
+ if (d->compactionCounter > 32 && d->compactionCounter >= (int)o->length/2)
+ compact();
+
+ // iterator hasn't changed
+ return it;
+}
+
+QJsonObject::iterator QJsonObject::find(const QString &key)
+{
+ int index = o ? o->indexOf(key) : 0;
+ if (index < 0)
+ index = o->length;
+ return iterator(this, index);
+}
+
+QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
+{
+ int index = o ? o->indexOf(key) : 0;
+ if (index < 0)
+ index = o->length;
+ return const_iterator(this, index);
+}
+
void QJsonObject::detach(uint reserve)
{
if (!d) {
@@ -308,7 +343,7 @@ void QJsonObject::compact() const
const_cast<QJsonObject *>(this)->o = static_cast<Private::Object *>(d->header->root());
}
-QString QJsonObject::keyAt(int i)
+QString QJsonObject::keyAt(int i) const
{
Q_ASSERT(o && i >= 0 && i < (int)o->length);
@@ -316,9 +351,10 @@ QString QJsonObject::keyAt(int i)
return e->key();
}
-QJsonValue QJsonObject::valueAt(int i)
+QJsonValue QJsonObject::valueAt(int i) const
{
- Q_ASSERT(o && i >= 0 && i < (int)o->length);
+ if (!o || i < 0 || i >= (int)o->length)
+ return QJsonValue(QJsonValue::Undefined);
Private::Entry *e = o->entryAt(i);
return QJsonValue(d, o, e->value);
diff --git a/src/qjsonobject.h b/src/qjsonobject.h
index dff0e9e..8bbbdd1 100644
--- a/src/qjsonobject.h
+++ b/src/qjsonobject.h
@@ -42,7 +42,7 @@
#ifndef QJSONOBJECT_H
#define QJSONOBJECT_H
-#include <qjsonglobal.h>
+#include <qjsonvalue.h>
#include <qvariant.h>
#include <qdebug.h>
@@ -73,7 +73,6 @@ public:
QJsonValue operator[] (const QString &key) const;
QJsonValueRef operator[] (const QString &key);
- void insert(const QString &key, const QJsonValue &value);
void remove(const QString &key);
QJsonValue take(const QString &key);
bool contains(const QString &key) const;
@@ -81,6 +80,124 @@ public:
bool operator==(const QJsonObject &other) const;
bool operator!=(const QJsonObject &other) const;
+ class const_iterator;
+
+ class iterator
+ {
+ friend class const_iterator;
+ friend class QJsonObject;
+ QJsonObject *o;
+ int i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef int difference_type;
+ typedef QJsonValue value_type;
+// typedef T *pointer;
+ typedef QJsonValueRef reference;
+
+ inline iterator() : o(0), i(0) {}
+ explicit inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
+
+ inline QString key() const { return o->keyAt(i); }
+ inline QJsonValueRef value() const { return QJsonValueRef(o, i); }
+ inline QJsonValueRef operator*() const { return QJsonValueRef(o, i); }
+ //inline T *operator->() const { return &concrete(i)->value; }
+ inline bool operator==(const iterator &other) const { return i == other.i; }
+ inline bool operator!=(const iterator &other) const { return i != other.i; }
+
+ inline iterator &operator++() { ++i; return *this; }
+ inline iterator operator++(int) { iterator r = *this; ++i; return r; }
+ inline iterator &operator--() { --i; return *this; }
+ inline iterator operator--(int) { iterator r = *this; --i; return r; }
+ inline iterator operator+(int j) const
+ { iterator r = *this; r.i += j; return r; }
+ inline iterator operator-(int j) const { return operator+(-j); }
+ inline iterator &operator+=(int j) { i += j; return *this; }
+ inline iterator &operator-=(int j) { i -= j; return *this; }
+
+#ifdef QT_STRICT_ITERATORS
+ private:
+#else
+ public:
+#endif
+ inline bool operator==(const const_iterator &other) const { return i == other.i; }
+ inline bool operator!=(const const_iterator &other) const { return i != other.i; }
+ };
+ friend class iterator;
+
+ class const_iterator
+ {
+ friend class iterator;
+ const QJsonObject *o;
+ int i;
+
+ public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef int difference_type;
+ typedef QJsonValue value_type;
+ //typedef const T *pointer;
+ typedef QJsonValue reference;
+
+ inline const_iterator() : o(0), i(0) {}
+ explicit inline const_iterator(const QJsonObject *obj, int index)
+ : o(obj), i(index) {}
+#ifdef QT_STRICT_ITERATORS
+ explicit inline const_iterator(const iterator &other)
+#else
+ inline const_iterator(const iterator &other)
+#endif
+ : o(other.o), i(other.i) {}
+
+ inline QString key() const { return o->keyAt(i); }
+ inline QJsonValue value() const { return o->valueAt(i); }
+ inline QJsonValue operator*() const { return o->valueAt(i); }
+ //inline const T *operator->() const { return &concrete(i)->value; }
+ inline bool operator==(const const_iterator &other) const { return i == other.i; }
+ inline bool operator!=(const const_iterator &other) const { return i != other.i; }
+
+ inline const_iterator &operator++() { ++i; return *this; }
+ inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; }
+ inline const_iterator &operator--() { --i; return *this; }
+ inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; }
+ inline const_iterator operator+(int j) const
+ { const_iterator r = *this; r.i += j; return r; }
+ inline const_iterator operator-(int j) const { return operator+(-j); }
+ inline const_iterator &operator+=(int j) { i += j; return *this; }
+ inline const_iterator &operator-=(int j) { i -= j; return *this; }
+
+#ifdef QT_STRICT_ITERATORS
+ private:
+ inline bool operator==(const iterator &o) const { return i == o.i; }
+ inline bool operator!=(const iterator &o) const { return i != o.i; }
+#endif
+ };
+ friend class const_iterator;
+
+ // STL style
+ inline iterator begin() { detach(); return iterator(this, 0); }
+ inline const_iterator begin() const { return const_iterator(this, 0); }
+ inline const_iterator constBegin() const { return const_iterator(this, 0); }
+ inline iterator end() { detach(); return iterator(this, size()); }
+ inline const_iterator end() const { return const_iterator(this, size()); }
+ inline const_iterator constEnd() const { return const_iterator(this, size()); }
+ iterator erase(iterator it);
+
+ // more Qt
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ iterator find(const QString &key);
+ const_iterator find(const QString &key) const { return constFind(key); }
+ const_iterator constFind(const QString &key) const;
+ iterator insert(const QString &key, const QJsonValue &value);
+
+ // STL compatibility
+ typedef QJsonValue mapped_type;
+ typedef QString key_type;
+ typedef int size_type;
+
+ inline bool empty() const { return isEmpty(); }
+
private:
friend class Private::Data;
friend class QJsonValue;
@@ -94,8 +211,8 @@ private:
void detach(uint reserve = 0);
void compact() const;
- QString keyAt(int i);
- QJsonValue valueAt(int i);
+ QString keyAt(int i) const;
+ QJsonValue valueAt(int i) const;
void setValueAt(int i, const QJsonValue &val);
Private::Data *d;
diff --git a/tests/auto/tst_qtjson.cpp b/tests/auto/tst_qtjson.cpp
index 735c892..6a818e7 100644
--- a/tests/auto/tst_qtjson.cpp
+++ b/tests/auto/tst_qtjson.cpp
@@ -70,6 +70,9 @@ private Q_SLOTS:
void testObjectNestedEmpty();
void testValueRef();
+ void testObjectIteration();
+
+ void testObjectFind();
void testDocument();
@@ -497,6 +500,89 @@ void TestQtJson::testValueRef()
QCOMPARE(object.size(), 2);
}
+void TestQtJson::testObjectIteration()
+{
+ QJsonObject object;
+ for (int i = 0; i < 10; ++i)
+ object[QString::number(i)] = i;
+
+ QCOMPARE(object.size(), 10);
+
+ for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) {
+ QJsonValue value = it.value();
+ QCOMPARE(it.key().toInt(), value.toInt());
+ }
+
+ {
+ QJsonObject object2 = object;
+ QVERIFY(object == object2);
+
+ QJsonValue val = *object2.begin();
+ object2.erase(object2.begin());
+ QCOMPARE(object.size(), 10);
+ QCOMPARE(object2.size(), 9);
+
+ for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) {
+ QJsonValue value = it.value();
+ QVERIFY(it.value() != val);
+ QCOMPARE(it.key().toInt(), value.toInt());
+ }
+ }
+
+ {
+ QJsonObject::Iterator it = object.begin();
+ it += 5;
+ QCOMPARE(QJsonValue(it.value()).toInt(), 5);
+ it -= 3;
+ QCOMPARE(QJsonValue(it.value()).toInt(), 2);
+ QJsonObject::Iterator it2 = it + 5;
+ QCOMPARE(QJsonValue(it2.value()).toInt(), 7);
+ it2 = it - 1;
+ QCOMPARE(QJsonValue(it2.value()).toInt(), 1);
+ }
+
+ {
+ QJsonObject::ConstIterator it = object.constBegin();
+ it += 5;
+ QCOMPARE(QJsonValue(it.value()).toInt(), 5);
+ it -= 3;
+ QCOMPARE(QJsonValue(it.value()).toInt(), 2);
+ QJsonObject::ConstIterator it2 = it + 5;
+ QCOMPARE(QJsonValue(it2.value()).toInt(), 7);
+ it2 = it - 1;
+ QCOMPARE(QJsonValue(it2.value()).toInt(), 1);
+ }
+
+ QJsonObject::Iterator it = object.begin();
+ while (!object.isEmpty())
+ it = object.erase(it);
+ QCOMPARE(object.size() , 0);
+ QVERIFY(it == object.end());
+}
+
+
+void TestQtJson::testObjectFind()
+{
+ QJsonObject object;
+ for (int i = 0; i < 10; ++i)
+ object[QString::number(i)] = i;
+
+ QCOMPARE(object.size(), 10);
+
+ QJsonObject::iterator it = object.find(QLatin1String("1"));
+ QCOMPARE((*it).toInt(), 1);
+ it = object.find(QLatin1String("11"));
+ QVERIFY((*it).type() == QJsonValue::Undefined);
+ QVERIFY(it == object.end());
+
+ QJsonObject::const_iterator cit = object.constFind(QLatin1String("1"));
+ QCOMPARE((*cit).toInt(), 1);
+ cit = object.constFind(QLatin1String("11"));
+ QVERIFY((*it).type() == QJsonValue::Undefined);
+ QVERIFY(it == object.end());
+}
+
+
void TestQtJson::testDocument()
{
QJsonDocument doc;