[libvirt] [PATCH 04/12] util: json: Add functions to convert JSON arrays from/to virBitmaps

Peter Krempa pkrempa at redhat.com
Wed Jan 28 10:30:29 UTC 2015


To be able to easily represent nodesets and other data stored in
virBitmaps in libvirt, this patch introduces a set of helpers that allow
to convert the bitmap to and from JSON value objects.
---
 src/libvirt_private.syms |   2 +
 src/util/virjson.c       | 113 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virjson.h       |   4 ++
 3 files changed, 119 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cc74e35..70c81a8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1514,6 +1514,7 @@ virJSONValueArrayGet;
 virJSONValueArraySize;
 virJSONValueFree;
 virJSONValueFromString;
+virJSONValueGetArrayAsBitmap;
 virJSONValueGetBoolean;
 virJSONValueGetNumberDouble;
 virJSONValueGetNumberInt;
@@ -1523,6 +1524,7 @@ virJSONValueGetNumberUlong;
 virJSONValueGetString;
 virJSONValueIsNull;
 virJSONValueNewArray;
+virJSONValueNewArrayFromBitmap;
 virJSONValueNewBoolean;
 virJSONValueNewNull;
 virJSONValueNewNumberDouble;
diff --git a/src/util/virjson.c b/src/util/virjson.c
index 9eb1bff..3e00650 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -99,6 +99,8 @@ struct _virJSONParser {
  *
  * a: json object, must be non-NULL
  * A: json object, omitted if NULL
+ * m: a bitmap represented as a JSON array, must be non-NULL
+ * M: a bitmap represented as a JSON array, omitted if NULL
  *
  * The value corresponds to the selected type.
  *
@@ -242,6 +244,28 @@ virJSONValueObjectAddVArgs(virJSONValuePtr obj,
             rc = virJSONValueObjectAppend(obj, key, val);
         }   break;

+        case 'M':
+        case 'm': {
+            virBitmapPtr map = va_arg(args, virBitmapPtr);
+            virJSONValuePtr jsonMap;
+
+            if (!map) {
+                if (type == 'M')
+                    continue;
+
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("argument key '%s' must not have null value"),
+                               key);
+                goto cleanup;
+            }
+
+            if (!(jsonMap = virJSONValueNewArrayFromBitmap(map)))
+                goto cleanup;
+
+            if ((rc = virJSONValueObjectAppend(obj, key, jsonMap)) < 0)
+                virJSONValueFree(jsonMap);
+        } break;
+
         default:
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("unsupported data type '%c' for arg '%s'"), type, key - 2);
@@ -941,6 +965,95 @@ virJSONValueGetBoolean(virJSONValuePtr val,
 }


+/**
+ * virJSONValueGetArrayAsBitmap:
+ * @val: JSON array to convert to bitmap
+ * @bitmap: New bitmap is allocated filled and returned via this argument
+ *
+ * Attempts a conversion of a JSON array to a bitmap. The members of the array
+ * must be non-negative integers for the conversion to succeed. This function
+ * does not report libvirt errors (except for out-of-memory) so that it can be
+ * used to probe that the array can be represented as a bitmap.
+ *
+ * Returns 0 on success and fills @bitmap; -1 on error and  @bitmap is set to
+ * NULL.
+ */
+int
+virJSONValueGetArrayAsBitmap(const virJSONValue *val,
+                             virBitmapPtr *bitmap)
+{
+    int ret = -1;
+    virJSONValuePtr elem;
+    size_t i;
+    unsigned long long *elems = NULL;
+    unsigned long long maxelem = 0;
+
+    *bitmap = NULL;
+
+    if (val->type != VIR_JSON_TYPE_ARRAY)
+        return -1;
+
+    if (VIR_ALLOC_N(elems, val->data.array.nvalues) < 0)
+        return -1;
+
+    /* first pass converts array members to numbers and finds the maximum */
+    for (i = 0; i < val->data.array.nvalues; i++) {
+        elem = val->data.array.values[i];
+
+        if (elem->type != VIR_JSON_TYPE_NUMBER ||
+            virStrToLong_ullp(elem->data.number, NULL, 10, &elems[i]) < 0)
+            goto cleanup;
+
+        if (elems[i] > maxelem)
+            maxelem = elems[i];
+    }
+
+    if (!(*bitmap = virBitmapNew(maxelem + 1)))
+        goto cleanup;
+
+    /* second pass sets the correct bits in the map */
+    for (i = 0; i < val->data.array.nvalues; i++)
+        ignore_value(virBitmapSetBit(*bitmap, elems[i]));
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(elems);
+
+    return ret;
+}
+
+
+virJSONValuePtr
+virJSONValueNewArrayFromBitmap(virBitmapPtr bitmap)
+{
+    virJSONValuePtr ret;
+    ssize_t pos = -1;
+
+    if (!(ret = virJSONValueNewArray()))
+        return NULL;
+
+    if (!bitmap)
+        return ret;
+
+    while ((pos = virBitmapNextSetBit(bitmap, pos)) > -1) {
+        virJSONValuePtr newelem;
+
+        if (!(newelem = virJSONValueNewNumberLong(pos)) ||
+            virJSONValueArrayAppend(ret, newelem) < 0) {
+            virJSONValueFree(newelem);
+            goto error;
+        }
+    }
+
+    return ret;
+
+ error:
+    virJSONValueFree(ret);
+    return NULL;
+}
+
+
 int
 virJSONValueIsNull(virJSONValuePtr val)
 {
diff --git a/src/util/virjson.h b/src/util/virjson.h
index fc05ad9..57010b0 100644
--- a/src/util/virjson.h
+++ b/src/util/virjson.h
@@ -25,6 +25,7 @@
 # define __VIR_JSON_H_

 # include "internal.h"
+# include "virbitmap.h"

 # include <stdarg.h>

@@ -102,6 +103,7 @@ virJSONValuePtr virJSONValueNewBoolean(int boolean);
 virJSONValuePtr virJSONValueNewNull(void);
 virJSONValuePtr virJSONValueNewArray(void);
 virJSONValuePtr virJSONValueNewObject(void);
+virJSONValuePtr virJSONValueNewArrayFromBitmap(virBitmapPtr bitmap);

 int virJSONValueObjectAppend(virJSONValuePtr object, const char *key, virJSONValuePtr value);
 int virJSONValueArrayAppend(virJSONValuePtr object, virJSONValuePtr value);
@@ -125,6 +127,8 @@ int virJSONValueGetNumberLong(virJSONValuePtr object, long long *value);
 int virJSONValueGetNumberUlong(virJSONValuePtr object, unsigned long long *value);
 int virJSONValueGetNumberDouble(virJSONValuePtr object, double *value);
 int virJSONValueGetBoolean(virJSONValuePtr object, bool *value);
+int virJSONValueGetArrayAsBitmap(const virJSONValue *val, virBitmapPtr *bitmap)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 int virJSONValueIsNull(virJSONValuePtr object);

 const char *virJSONValueObjectGetString(virJSONValuePtr object, const char *key);
-- 
2.2.2




More information about the libvir-list mailing list