QCborValueRef: merge the operator[] into a template

Change-Id: I5e52dc5b093c43a3b678fffd16b6e94ad9d3f39b
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Thiago Macieira 2021-11-12 13:20:22 -08:00
parent 832fcbf37f
commit afe2f80c6a
3 changed files with 40 additions and 147 deletions

View File

@ -275,6 +275,7 @@ public:
private: private:
void detach(qsizetype reserve = 0); void detach(qsizetype reserve = 0);
friend QCborContainerPrivate;
friend QCborValue; friend QCborValue;
friend QCborValueRef; friend QCborValueRef;
friend class QJsonPrivate::Variant; friend class QJsonPrivate::Variant;

View File

@ -766,6 +766,16 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor; using namespace QtCbor;
static QCborContainerPrivate *assignContainer(QCborContainerPrivate *&d, QCborContainerPrivate *x)
{
if (d == x)
return d;
if (d)
d->deref();
x->ref.ref();
return d = x;
}
static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
{ {
qint64 tag = d->elements.at(0).value; qint64 tag = d->elements.at(0).value;
@ -2242,22 +2252,6 @@ static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
return map; return map;
} }
/*!
\internal
*/
[[maybe_unused]]
static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
{
auto replace = QCborContainerPrivate::detach(container, size);
Q_ASSERT(replace);
if (replace != container) {
if (container)
container->deref();
replace->ref.ref();
}
return replace;
}
/*! /*!
\internal \internal
*/ */
@ -2287,12 +2281,32 @@ QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
self = QCborValue(QCborValue::Map); self = QCborValue(QCborValue::Map);
QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key); QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
if (result.d != self.container) { assignContainer(self.container, result.d);
if (self.container) return result;
self.container->deref();
self.container = result.d;
self.container->ref.ref();
} }
template<typename KeyType> QCborValueRef
QCborContainerPrivate::findOrAddMapKey(QCborValueRef self, KeyType key)
{
auto &e = self.d->elements[self.i];
// we need a map, so convert if necessary
if (e.flags & QtCbor::Element::IsContainer) {
if (e.type == QCborValue::Array) {
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
qSwap(e.container, repack.container);
} else if (e.type != QCborValue::Map) {
e.container->deref();
e.container = nullptr;
}
} else {
e.container = nullptr;
}
e.flags = QtCbor::Element::IsContainer;
e.type = QCborValue::Map;
QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
assignContainer(e.container, result.d);
return result; return result;
} }
@ -2733,48 +2747,7 @@ const QCborValue QCborValueRef::operator[](qint64 key) const
*/ */
QCborValueRef QCborValueRef::operator[](const QString &key) QCborValueRef QCborValueRef::operator[](const QString &key)
{ {
auto &e = d->elements[i]; return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
qsizetype size = 0;
if (e.flags & QtCbor::Element::IsContainer) {
if (e.container) {
if (e.type == QCborValue::Array) {
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
qSwap(e.container, repack.container);
} else if (e.type != QCborValue::Map) {
e.container->deref();
e.container = nullptr;
}
}
e.type = QCborValue::Map;
if (e.container)
size = e.container->elements.size();
} else {
// Stomp any prior e.value, replace with a map (that we'll grow)
e.container = nullptr;
e.type = QCborValue::Map;
e.flags = QtCbor::Element::IsContainer;
}
qsizetype index = size + 1;
bool found = false;
if (e.container) {
QCborMap proxy(*e.container);
auto it = proxy.constFind(key);
if (it < proxy.constEnd()) {
found = true;
index = it.item.i;
}
}
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
Q_ASSERT(e.container);
if (!found) {
e.container->append(key);
e.container->append(QCborValue());
}
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
Q_ASSERT(index < e.container->elements.size());
return { e.container, index };
} }
/*! /*!
@ -2794,48 +2767,7 @@ QCborValueRef QCborValueRef::operator[](const QString &key)
*/ */
QCborValueRef QCborValueRef::operator[](QLatin1String key) QCborValueRef QCborValueRef::operator[](QLatin1String key)
{ {
auto &e = d->elements[i]; return QCborContainerPrivate::findOrAddMapKey(*this, key);
qsizetype size = 0;
if (e.flags & QtCbor::Element::IsContainer) {
if (e.container) {
if (e.type == QCborValue::Array) {
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
qSwap(e.container, repack.container);
} else if (e.type != QCborValue::Map) {
e.container->deref();
e.container = nullptr;
}
}
e.type = QCborValue::Map;
if (e.container)
size = e.container->elements.size();
} else {
// Stomp any prior e.value, replace with a map (that we'll grow)
e.container = nullptr;
e.type = QCborValue::Map;
e.flags = QtCbor::Element::IsContainer;
}
qsizetype index = size + 1;
bool found = false;
if (e.container) {
QCborMap proxy(*e.container);
auto it = proxy.constFind(key);
if (it < proxy.constEnd()) {
found = true;
index = it.item.i;
}
}
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
Q_ASSERT(e.container);
if (!found) {
e.container->append(key);
e.container->append(QCborValue());
}
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
Q_ASSERT(index < e.container->elements.size());
return { e.container, index };
} }
/*! /*!
@ -2862,48 +2794,7 @@ QCborValueRef QCborValueRef::operator[](qint64 key)
e.flags |= QtCbor::Element::IsContainer; e.flags |= QtCbor::Element::IsContainer;
return { e.container, qsizetype(key) }; return { e.container, qsizetype(key) };
} }
qsizetype size = 0; return QCborContainerPrivate::findOrAddMapKey(*this, key);
if (e.flags & QtCbor::Element::IsContainer) {
if (e.container) {
if (e.type == QCborValue::Array) {
QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
qSwap(e.container, repack.container);
} else if (e.type != QCborValue::Map) {
e.container->deref();
e.container = nullptr;
}
}
e.type = QCborValue::Map;
if (e.container)
size = e.container->elements.size();
} else {
// Stomp any prior e.value, replace with a map (that we'll grow)
e.container = nullptr;
e.type = QCborValue::Map;
e.flags = QtCbor::Element::IsContainer;
}
Q_ASSERT(!(size & 1));
qsizetype index = size + 1;
bool found = false;
if (e.container) {
QCborMap proxy(*e.container);
auto it = proxy.constFind(key);
if (it < proxy.constEnd()) {
found = true;
index = it.item.i;
}
}
e.container = maybeDetach(e.container, size + (found ? 0 : 2));
Q_ASSERT(e.container);
if (!found) {
e.container->append(key);
e.container->append(QCborValue());
}
Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
Q_ASSERT(index < e.container->elements.size());
return { e.container, index };
} }
#endif // < Qt 7 #endif // < Qt 7

View File

@ -473,6 +473,7 @@ public:
} }
template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborMap &map, KeyType key); template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborMap &map, KeyType key);
template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValue &self, KeyType key); template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValue &self, KeyType key);
template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValueRef self, KeyType key);
#if QT_CONFIG(cborstreamreader) #if QT_CONFIG(cborstreamreader)
void decodeValueFromCbor(QCborStreamReader &reader, int remainingStackDepth); void decodeValueFromCbor(QCborStreamReader &reader, int remainingStackDepth);