*/
QDict *qobject_to_qdict(const QObject *obj)
{
- if (qobject_type(obj) != QTYPE_QDICT)
+ if (!obj || qobject_type(obj) != QTYPE_QDICT) {
return NULL;
-
+ }
return container_of(obj, QDict, base);
}
*/
int64_t qdict_get_int(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT);
- return qint_get_int(qobject_to_qint(obj));
+ return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
}
/**
*
* Return bool mapped by 'key'.
*/
-int qdict_get_bool(const QDict *qdict, const char *key)
+bool qdict_get_bool(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL);
- return qbool_get_int(qobject_to_qbool(obj));
+ return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key)));
}
/**
*/
QDict *qdict_get_qdict(const QDict *qdict, const char *key)
{
- return qobject_to_qdict(qdict_get_obj(qdict, key, QTYPE_QDICT));
+ return qobject_to_qdict(qdict_get(qdict, key));
}
/**
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
int64_t def_value)
{
- QObject *obj;
-
- obj = qdict_get(qdict, key);
- if (!obj || qobject_type(obj) != QTYPE_QINT)
- return def_value;
+ QInt *qint = qobject_to_qint(qdict_get(qdict, key));
- return qint_get_int(qobject_to_qint(obj));
+ return qint ? qint_get_int(qint) : def_value;
}
/**
* dictionary or if the stored object is not of QBool type
* 'def_value' will be returned.
*/
-int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value)
+bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
{
- QObject *obj;
-
- obj = qdict_get(qdict, key);
- if (!obj || qobject_type(obj) != QTYPE_QBOOL)
- return def_value;
+ QBool *qbool = qobject_to_qbool(qdict_get(qdict, key));
- return qbool_get_int(qobject_to_qbool(obj));
+ return qbool ? qbool_get_bool(qbool) : def_value;
}
/**
g_free(qdict);
}
+/**
+ * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the
+ * value of 'key' in 'src' is copied there (and the refcount increased
+ * accordingly).
+ */
+void qdict_copy_default(QDict *dst, QDict *src, const char *key)
+{
+ QObject *val;
+
+ if (qdict_haskey(dst, key)) {
+ return;
+ }
+
+ val = qdict_get(src, key);
+ if (val) {
+ qobject_incref(val);
+ qdict_put_obj(dst, key, val);
+ }
+}
+
+/**
+ * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a
+ * new QString initialised by 'val' is put there.
+ */
+void qdict_set_default_str(QDict *dst, const char *key, const char *val)
+{
+ if (qdict_haskey(dst, key)) {
+ return;
+ }
+
+ qdict_put(dst, key, qstring_from_str(val));
+}
+
static void qdict_flatten_qdict(QDict *qdict, QDict *target,
const char *prefix);
}
}
-static bool qdict_has_prefixed_entries(const QDict *src, const char *start)
+static int qdict_count_prefixed_entries(const QDict *src, const char *start)
{
const QDictEntry *entry;
+ int count = 0;
for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
if (strstart(entry->key, start, NULL)) {
- return true;
+ if (count == INT_MAX) {
+ return -ERANGE;
+ }
+ count++;
}
}
- return false;
+ return count;
}
/**
snprintf_ret = snprintf(prefix, 32, "%u.", i);
assert(snprintf_ret < 32);
- is_subqdict = qdict_has_prefixed_entries(src, prefix);
+ /* Overflow is the same as positive non-zero results */
+ is_subqdict = qdict_count_prefixed_entries(src, prefix);
// There may be either a single subordinate object (named "%u") or
// multiple objects (each with a key prefixed "%u."), but not both.
qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
}
}
+
+/**
+ * qdict_array_entries(): Returns the number of direct array entries if the
+ * sub-QDict of src specified by the prefix in subqdict (or src itself for
+ * prefix == "") is valid as an array, i.e. the length of the created list if
+ * the sub-QDict would become empty after calling qdict_array_split() on it. If
+ * the array is not valid, -EINVAL is returned.
+ */
+int qdict_array_entries(QDict *src, const char *subqdict)
+{
+ const QDictEntry *entry;
+ unsigned i;
+ unsigned entries = 0;
+ size_t subqdict_len = strlen(subqdict);
+
+ assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
+
+ /* qdict_array_split() loops until UINT_MAX, but as we want to return
+ * negative errors, we only have a signed return value here. Any additional
+ * entries will lead to -EINVAL. */
+ for (i = 0; i < INT_MAX; i++) {
+ QObject *subqobj;
+ int subqdict_entries;
+ size_t slen = 32 + subqdict_len;
+ char indexstr[slen], prefix[slen];
+ size_t snprintf_ret;
+
+ snprintf_ret = snprintf(indexstr, slen, "%s%u", subqdict, i);
+ assert(snprintf_ret < slen);
+
+ subqobj = qdict_get(src, indexstr);
+
+ snprintf_ret = snprintf(prefix, slen, "%s%u.", subqdict, i);
+ assert(snprintf_ret < slen);
+
+ subqdict_entries = qdict_count_prefixed_entries(src, prefix);
+ if (subqdict_entries < 0) {
+ return subqdict_entries;
+ }
+
+ /* There may be either a single subordinate object (named "%u") or
+ * multiple objects (each with a key prefixed "%u."), but not both. */
+ if (subqobj && subqdict_entries) {
+ return -EINVAL;
+ } else if (!subqobj && !subqdict_entries) {
+ break;
+ }
+
+ entries += subqdict_entries ? subqdict_entries : 1;
+ }
+
+ /* Consider everything handled that isn't part of the given sub-QDict */
+ for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
+ if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
+ entries++;
+ }
+ }
+
+ /* Anything left in the sub-QDict that wasn't handled? */
+ if (qdict_size(src) != entries) {
+ return -EINVAL;
+ }
+
+ return i;
+}
+
+/**
+ * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all
+ * elements from src to dest.
+ *
+ * If an element from src has a key already present in dest, it will not be
+ * moved unless overwrite is true.
+ *
+ * If overwrite is true, the conflicting values in dest will be discarded and
+ * replaced by the corresponding values from src.
+ *
+ * Therefore, with overwrite being true, the src QDict will always be empty when
+ * this function returns. If overwrite is false, the src QDict will be empty
+ * iff there were no conflicts.
+ */
+void qdict_join(QDict *dest, QDict *src, bool overwrite)
+{
+ const QDictEntry *entry, *next;
+
+ entry = qdict_first(src);
+ while (entry) {
+ next = qdict_next(src, entry);
+
+ if (overwrite || !qdict_haskey(dest, entry->key)) {
+ qobject_incref(entry->value);
+ qdict_put_obj(dest, entry->key, entry->value);
+ qdict_del(src, entry->key);
+ }
+
+ entry = next;
+ }
+}