From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47599) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YroCL-0005r7-0r for qemu-devel@nongnu.org; Mon, 11 May 2015 09:56:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YroCK-0003vZ-3Z for qemu-devel@nongnu.org; Mon, 11 May 2015 09:56:44 -0400 Message-ID: <5550B512.7090306@redhat.com> Date: Mon, 11 May 2015 15:56:34 +0200 From: Max Reitz MIME-Version: 1.0 References: <1431105726-3682-1-git-send-email-kwolf@redhat.com> <1431105726-3682-2-git-send-email-kwolf@redhat.com> In-Reply-To: <1431105726-3682-2-git-send-email-kwolf@redhat.com> Content-Type: text/plain; charset=iso-8859-15; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 01/34] qdict: Add qdict_array_entries() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf , qemu-block@nongnu.org Cc: armbru@redhat.com, qemu-devel@nongnu.org On 08.05.2015 19:21, Kevin Wolf wrote: > Signed-off-by: Kevin Wolf > --- > include/qapi/qmp/qdict.h | 1 + > qobject/qdict.c | 68 +++++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 65 insertions(+), 4 deletions(-) > > diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h > index d68f4eb..d20db94 100644 > --- a/include/qapi/qmp/qdict.h > +++ b/include/qapi/qmp/qdict.h > @@ -70,6 +70,7 @@ void qdict_flatten(QDict *qdict); > > void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start); > void qdict_array_split(QDict *src, QList **dst); > +int qdict_array_entries(QDict *src, const char *subqdict); > > void qdict_join(QDict *dest, QDict *src, bool overwrite); > > diff --git a/qobject/qdict.c b/qobject/qdict.c > index ea239f0..2fcb7fe 100644 > --- a/qobject/qdict.c > +++ b/qobject/qdict.c > @@ -597,17 +597,18 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start) > } > } > > -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; > + count++; On one hand a dumb question, but on the other hand we probably do need to consider it: What about overflows? I think we can avoid thinking about them by using size_t for all the counters. > } > } > > - return false; > + return count; > } > > /** > @@ -646,7 +647,7 @@ void qdict_array_split(QDict *src, QList **dst) > snprintf_ret = snprintf(prefix, 32, "%u.", i); > assert(snprintf_ret < 32); > > - is_subqdict = qdict_has_prefixed_entries(src, prefix); > + 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. > @@ -667,6 +668,65 @@ void qdict_array_split(QDict *src, QList **dst) > } > > /** > + * qdict_array_valid(): Returns the number of direct array entries if the (As Eric said, should be "qdict_array_entries():") > + * 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, -1 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] == '.'); > + > + for (i = 0; i < UINT_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); > + > + /* 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 -1; > + } 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 -1; > + } > + > + return i; Again, possible overflow that can be avoided by returning size_t. Max > +} > + > +/** > * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all > * elements from src to dest. > *