[libvirt] [PATCH v4 2/9] New functions for virBitmap

Osier Yang jyang at redhat.com
Tue Sep 18 07:27:00 UTC 2012


On 2012年09月14日 15:46, Hu Tao wrote:
> In many places we store bitmap info in a chunk of data
> (pointed to by a char *), and have redundant codes to
> set/unset bits. This patch extends virBitmap, and convert
> those codes to use virBitmap in subsequent patches.
> ---
>   .gitignore               |    1 +
>   src/libvirt_private.syms |   11 ++
>   src/util/bitmap.c        |  405 +++++++++++++++++++++++++++++++++++++++++++++-
>   src/util/bitmap.h        |   34 ++++
>   tests/Makefile.am        |    7 +-
>   tests/virbitmaptest.c    |  362 +++++++++++++++++++++++++++++++++++++++++
>   6 files changed, 818 insertions(+), 2 deletions(-)
>   create mode 100644 tests/virbitmaptest.c
>
> diff --git a/.gitignore b/.gitignore
> index d998f0e..1ca537e 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -157,6 +157,7 @@
>   /tests/utiltest
>   /tests/viratomictest
>   /tests/virauthconfigtest
> +/tests/virbitmaptest
>   /tests/virbuftest
>   /tests/virdrivermoduletest
>   /tests/virhashtest
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 557fa0e..da0e647 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -6,13 +6,24 @@
>   #
>
>   # bitmap.h
> +virBitmapClearAll;
>   virBitmapClearBit;
>   virBitmapCopy;
> +virBitmapEqual;
> +virBitmapFormat;
>   virBitmapFree;
>   virBitmapGetBit;
> +virBitmapIsAllSet;
>   virBitmapNew;
> +virBitmapNewCopy;
> +virBitmapNewData;
> +virBitmapNextSetBit;
> +virBitmapParse;
> +virBitmapSetAll;
>   virBitmapSetBit;
> +virBitmapSize;
>   virBitmapString;
> +virBitmapToData;
>
>
>   # buf.h
> diff --git a/src/util/bitmap.c b/src/util/bitmap.c
> index dc9c28a..51e567a 100644
> --- a/src/util/bitmap.c
> +++ b/src/util/bitmap.c
> @@ -33,6 +33,8 @@
>   #include "bitmap.h"
>   #include "memory.h"
>   #include "buf.h"
> +#include "util.h"
> +#include "c-ctype.h"
>
>
>   struct _virBitmap {
> @@ -145,6 +147,12 @@ int virBitmapClearBit(virBitmapPtr bitmap, size_t b)
>       return 0;
>   }
>
> +/* Helper function. caller must ensure b<  bitmap->max_bit */
> +static bool virBitmapIsSet(virBitmapPtr bitmap, size_t b)
> +{
> +    return !!(bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)]&  VIR_BITMAP_BIT(b));
> +}
> +
>   /**
>    * virBitmapGetBit:
>    * @bitmap: Pointer to bitmap
> @@ -161,7 +169,7 @@ int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
>       if (bitmap->max_bit<= b)
>           return -1;
>
> -    *result = !!(bitmap->map[VIR_BITMAP_UNIT_OFFSET(b)]&  VIR_BITMAP_BIT(b));
> +    *result = virBitmapIsSet(bitmap, b);
>       return 0;
>   }
>
> @@ -195,3 +203,398 @@ char *virBitmapString(virBitmapPtr bitmap)
>
>       return virBufferContentAndReset(&buf);
>   }
> +
> +/**
> + * virBitmapFormat:
> + * @bitmap: the bitmap
> + *
> + * This function is the counterpart of virBitmapParse. This function creates
> + * a human-readable string representing the bits in bitmap.
> + *
> + * See virBitmapParse for the format of @str.
> + *
> + * Returns the string on success or NULL otherwise. Caller should call
> + * VIR_FREE to free the string.
> + */
> +char *virBitmapFormat(virBitmapPtr bitmap)
> +{
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +    bool first = true;
> +    int start, cur, prev;
> +
> +    if (!bitmap)
> +        return NULL;
> +
> +    cur = virBitmapNextSetBit(bitmap, -1);
> +    if (cur<  0)
> +        return strdup("");
> +
> +    start = prev = cur;
> +    while (prev>= 0) {
> +        cur = virBitmapNextSetBit(bitmap, prev);
> +
> +        if (cur == prev + 1) {
> +            prev = cur;
> +            continue;
> +        }
> +
> +        /* cur<  0 or cur>  prev + 1 */
> +
> +        if (!first)
> +            virBufferAddLit(&buf, ",");
> +        else
> +            first = false;
> +
> +        if (prev == start)
> +            virBufferAsprintf(&buf, "%d", start);
> +        else
> +            virBufferAsprintf(&buf, "%d-%d", start, prev);
> +
> +        start = prev = cur;
> +    }
> +
> +    if (virBufferError(&buf)) {
> +        virBufferFreeAndReset(&buf);
> +        return NULL;
> +    }
> +
> +    return virBufferContentAndReset(&buf);
> +}
> +
> +/**
> + * virBitmapParse:
> + * @str: points to a string representing a human-readable bitmap
> + * @bitmap: a bitmap created from @str
> + * @bitmapSize: the upper limit of num of bits in created bitmap
> + *
> + * This function is the counterpart of virBitmapFormat. This function creates
> + * a bitmap, in which bits are set according to the content of @str.
> + *
> + * @str is a comma separated string of fields N, which means a number of bit
> + * to set, and ^N, which means to unset the bit, and N-M for ranges of bits
> + * to set.
> + *
> + * Returns the number of bits set in @bitmap, or -1 in case of error.
> + */
> +
> +int virBitmapParse(const char *str,
> +                   char sep,
> +                   virBitmapPtr *bitmap,
> +                   size_t bitmapSize)
> +{
> +    int ret = 0;
> +    bool neg = false;
> +    const char *cur;
> +    char *tmp;
> +    int i, start, last;
> +
> +    if (!str)
> +        return -1;
> +
> +    cur = str;
> +    virSkipSpaces(&cur);
> +
> +    if (*cur == 0)
> +        return -1;
> +
> +    *bitmap = virBitmapNew(bitmapSize);
> +    if (!*bitmap)
> +        return -1;
> +
> +    while (*cur != 0&&  *cur != sep) {
> +        /*
> +         * 3 constructs are allowed:
> +         *     - N   : a single CPU number
> +         *     - N-M : a range of CPU numbers with N<  M
> +         *     - ^N  : remove a single CPU number from the current set
> +         */
> +        if (*cur == '^') {
> +            cur++;
> +            neg = true;
> +        }
> +
> +        if (!c_isdigit(*cur))
> +            goto parse_error;
> +
> +        if (virStrToLong_i(cur,&tmp, 10,&start)<  0)
> +            goto parse_error;
> +        if (start<  0)
> +            goto parse_error;
> +
> +        cur = tmp;
> +
> +        virSkipSpaces(&cur);
> +
> +        if (*cur == ',' || *cur == 0 || *cur == sep) {
> +            if (neg) {
> +                if (virBitmapIsSet(*bitmap, start)) {
> +                    ignore_value(virBitmapClearBit(*bitmap, start));
> +                    ret--;
> +                }
> +            } else {
> +                if (!virBitmapIsSet(*bitmap, start)) {
> +                    ignore_value(virBitmapSetBit(*bitmap, start));
> +                    ret++;
> +                }
> +            }
> +        } else if (*cur == '-') {
> +            if (neg)
> +                goto parse_error;
> +
> +            cur++;
> +            virSkipSpaces(&cur);
> +
> +            if (virStrToLong_i(cur,&tmp, 10,&last)<  0)
> +                goto parse_error;
> +            if (last<  start)
> +                goto parse_error;
> +
> +            cur = tmp;
> +
> +            for (i = start; i<= last; i++) {
> +                if (!virBitmapIsSet(*bitmap, i)) {
> +                    ignore_value(virBitmapSetBit(*bitmap, i));
> +                    ret++;
> +                }
> +            }
> +
> +            virSkipSpaces(&cur);
> +        }
> +
> +        if (*cur == ',') {
> +            cur++;
> +            virSkipSpaces(&cur);
> +            neg = false;
> +        } else if(*cur == 0 || *cur == sep) {
> +            break;
> +        } else {
> +            goto parse_error;
> +        }
> +    }
> +
> +    return ret;
> +
> +parse_error:
> +    virBitmapFree(*bitmap);
> +    *bitmap = NULL;
> +    return -1;
> +}
> +
> +/**
> + * virBitmapNewCopy:
> + * @src: the source bitmap.
> + *
> + * Makes a copy of bitmap @src.
> + *
> + * returns the copied bitmap on success, or NULL otherwise. Caller
> + * should call virBitmapFree to free the returned bitmap.
> + */
> +virBitmapPtr virBitmapNewCopy(virBitmapPtr src)
> +{
> +    virBitmapPtr dst;
> +
> +    if ((dst = virBitmapNew(src->max_bit)) == NULL)
> +        return NULL;
> +
> +    if (virBitmapCopy(dst, src) != 0) {
> +        virBitmapFree(dst);
> +        return NULL;
> +    }
> +
> +    return dst;
> +}
> +
> +/**
> + * virBitmapNewData:
> + * @data: the data
> + * @len: length of @data in bytes
> + *
> + * Allocate a bitmap from a chunk of data containing bits
> + * information
> + *
> + * Returns a pointer to the allocated bitmap or NULL if
> + * memory cannot be allocated.
> + */
> +virBitmapPtr virBitmapNewData(void *data, int len)
> +{
> +    virBitmapPtr bitmap;
> +    int i;
> +
> +    bitmap = virBitmapNew(len * CHAR_BIT);
> +    if (!bitmap)
> +        return NULL;
> +
> +    memcpy(bitmap->map, data, len);
> +    for (i = 0; i<  bitmap->map_len; i++)
> +        bitmap->map[i] = le64toh(bitmap->map[i]);


le64toh is not portable. Such as on mingw platform.

> +
> +    return bitmap;
> +}
> +
> +/**
> + * virBitmapToData:
> + * @data: the data
> + * @len: len of @data in byte
> + *
> + * Convert a bitmap to a chunk of data containing bits information.
> + * Data consists of sequential bytes, with lower bytes containing
> + * lower bits.
> + *
> + * Returns 0 on success, -1 otherwise.
> + */
> +int virBitmapToData(virBitmapPtr bitmap, unsigned char **data, int *dataLen)
> +{
> +    int len;
> +    unsigned long *l;
> +    int i;
> +
> +    len = bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT);
> +
> +    if (VIR_ALLOC_N(*data, len)<  0)
> +        return -1;
> +
> +    memcpy(*data, bitmap->map, len);
> +    *dataLen = len;
> +
> +    l = (unsigned long *)*data;
> +    for (i = 0; i<  bitmap->map_len; i++, l++)
> +        *l = htole64(*l);

Likewise.

> +
> +    return 0;
> +}
> +
> +/**
> + * virBitmapEqual:
> + * @b1: bitmap 1
> + * @b2: bitmap 2
> + *
> + * Compares two bitmaps, whose lengths can be different from each other.
> + *
> + * Returns true if two bitmaps have exactly the same set of bits set,
> + * otherwise false.
> + */
> +bool virBitmapEqual(virBitmapPtr b1, virBitmapPtr b2)
> +{
> +    virBitmapPtr tmp;
> +    int i;
> +
> +    if (b1->max_bit>  b2->max_bit) {
> +        tmp = b1;
> +        b1 = b2;
> +        b2 = tmp;
> +    }
> +
> +    /* Now b1 is the smaller one, if not equal */
> +
> +    for (i = 0; i<  b1->map_len; i++) {
> +        if (b1->map[i] != b2->map[i])
> +            return false;
> +    }
> +
> +    for (; i<  b2->map_len; i++) {
> +        if (b2->map[i])
> +            return false;
> +    }
> +
> +    return true;
> +}
> +
> +size_t virBitmapSize(virBitmapPtr bitmap)
> +{
> +    return bitmap->max_bit;
> +}
> +
> +/**
> + * virBitmapSetAll:
> + * @bitmap: the bitmap
> + *
> + * set all bits in @bitmap.
> + */
> +void virBitmapSetAll(virBitmapPtr bitmap)
> +{
> +    memset(bitmap->map, 0xff,
> +           bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT));
> +}
> +
> +/**
> + * virBitmapClearAll:
> + * @bitmap: the bitmap
> + *
> + * clear all bits in @bitmap.
> + */
> +void virBitmapClearAll(virBitmapPtr bitmap)
> +{
> +    memset(bitmap->map, 0,
> +           bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT));
> +}
> +
> +/**
> + * virBitmapIsAllSet:
> + * @bitmap: the bitmap to check
> + *
> + * check if all bits in @bitmap are set.
> + */
> +bool virBitmapIsAllSet(virBitmapPtr bitmap)
> +{
> +    int i;
> +    int unusedBits;
> +    size_t sz;
> +
> +    unusedBits = bitmap->map_len * VIR_BITMAP_BITS_PER_UNIT - bitmap->max_bit;
> +
> +    sz = bitmap->map_len;
> +    if (unusedBits>  0)
> +        sz--;
> +
> +    for (i = 0; i<  sz; i++)
> +        if (bitmap->map[i] != -1)
> +            return false;
> +
> +    if (unusedBits>  0) {
> +        if ((bitmap->map[sz]&  ((1U<<  (VIR_BITMAP_BITS_PER_UNIT - unusedBits)) - 1))
> +            != ((1U<<  (VIR_BITMAP_BITS_PER_UNIT - unusedBits)) - 1))
> +            return false;
> +    }
> +
> +    return true;
> +}
> +
> +/**
> + * virBitmapNextSetBit:
> + * @bitmap: the bitmap
> + * @pos: the position after which to search for a set bit
> + *
> + * search the first set bit after position @pos in bitmap @bitmap.
> + * @pos can be -1 to search for the first set bit. Position starts
> + * at 0.
> + *
> + * returns the position of the found bit, or -1 if no bit found.
> + */
> +int virBitmapNextSetBit(virBitmapPtr bitmap, int pos)
> +{
> +    int nl;
> +    int nb;
> +    unsigned long bits;
> +
> +    if (pos<  0)
> +        pos = -1;
> +
> +    pos++;
> +
> +    if (pos>= bitmap->max_bit)
> +        return -1;
> +
> +    nl = pos / VIR_BITMAP_BITS_PER_UNIT;
> +    nb = pos % VIR_BITMAP_BITS_PER_UNIT;
> +
> +    bits = bitmap->map[nl]&  ~((1UL<<  nb) - 1);
> +
> +    while (bits == 0&&  ++nl<  bitmap->map_len) {
> +        bits = bitmap->map[nl];
> +    }
> +
> +    if (bits == 0)
> +        return -1;
> +
> +    return ffsl(bits) - 1 + nl * VIR_BITMAP_BITS_PER_UNIT;

And ffsl.

> +}
> diff --git a/src/util/bitmap.h b/src/util/bitmap.h
> index 2609509..06c577f 100644
> --- a/src/util/bitmap.h
> +++ b/src/util/bitmap.h
> @@ -68,4 +68,38 @@ int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
>   char *virBitmapString(virBitmapPtr bitmap)
>       ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
>
> +char *virBitmapFormat(virBitmapPtr bitmap)
> +    ATTRIBUTE_NONNULL(1);
> +
> +int virBitmapParse(const char *str,
> +                   char sep,
> +                   virBitmapPtr *bitmap,
> +                   size_t bitmapSize)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
> +
> +virBitmapPtr virBitmapNewCopy(virBitmapPtr src) ATTRIBUTE_NONNULL(1);
> +
> +virBitmapPtr virBitmapNewData(void *data, int len) ATTRIBUTE_NONNULL(1);
> +
> +int virBitmapToData(virBitmapPtr bitmap, unsigned char **data, int *dataLen)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
> +bool virBitmapEqual(virBitmapPtr b1, virBitmapPtr b2)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
> +size_t virBitmapSize(virBitmapPtr bitmap)
> +    ATTRIBUTE_NONNULL(1);
> +
> +void virBitmapSetAll(virBitmapPtr bitmap)
> +    ATTRIBUTE_NONNULL(1);
> +
> +void virBitmapClearAll(virBitmapPtr bitmap)
> +    ATTRIBUTE_NONNULL(1);
> +
> +bool virBitmapIsAllSet(virBitmapPtr bitmap)
> +    ATTRIBUTE_NONNULL(1);
> +
> +int virBitmapNextSetBit(virBitmapPtr bitmap, int pos)
> +    ATTRIBUTE_NONNULL(1);
> +
>   #endif
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index c5cecaa..8dbad97 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -92,7 +92,8 @@ test_programs = virshtest sockettest \
>   	viratomictest \
>   	utiltest virnettlscontexttest shunloadtest \
>   	virtimetest viruritest virkeyfiletest \
> -	virauthconfigtest
> +	virauthconfigtest \
> +	virbitmaptest
>
>   if WITH_SECDRIVER_SELINUX
>   test_programs += securityselinuxtest
> @@ -589,6 +590,10 @@ viratomictest_SOURCES = \
>   	viratomictest.c testutils.h testutils.c
>   viratomictest_LDADD = $(LDADDS)
>
> +virbitmaptest_SOURCES = \
> +	virbitmaptest.c testutils.h testutils.c
> +virbitmaptest_LDADD = $(LDADDS)
> +
>   jsontest_SOURCES = \
>   	jsontest.c testutils.h testutils.c
>   jsontest_LDADD = $(LDADDS)
> diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
> new file mode 100644
> index 0000000..0975996
> --- /dev/null
> +++ b/tests/virbitmaptest.c
> @@ -0,0 +1,362 @@
> +/*
> + * Copyright (C) 2012 Fujitsu.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library;  If not, see
> + *<http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#include<config.h>
> +
> +#include "testutils.h"
> +
> +#include "bitmap.h"
> +
> +static int test1(const void *data ATTRIBUTE_UNUSED)
> +{
> +    virBitmapPtr bitmap;
> +    int size;
> +    int bit;
> +    bool result;
> +
> +    size = 1024;
> +    bit = 100;
> +    bitmap = virBitmapNew(size);
> +    if (virBitmapSetBit(bitmap, bit)<  0)
> +        return -1;
> +
> +    if (virBitmapGetBit(bitmap, bit,&result)<  0)
> +        return -1;
> +
> +    if (!result)
> +        return -1;
> +
> +    if (virBitmapGetBit(bitmap, bit + 1,&result)<  0)
> +        return -1;
> +
> +    if (result)
> +        return -1;
> +
> +    return 0;
> +}
> +
> +int testBit(virBitmapPtr bitmap,
> +            unsigned int start,
> +            unsigned int end,
> +            bool expected)
> +{
> +    int i;
> +    bool result;
> +
> +    for (i = start; i<= end; i++) {
> +        if (virBitmapGetBit(bitmap, i,&result)<  0)
> +            return -1;
> +        if (result == expected)
> +            return 0;
> +    }
> +
> +    return -1;
> +}
> +
> +static int test2(const void *data ATTRIBUTE_UNUSED)
> +{
> +    const char *bitsString1 = "1-32,50,88-99,1021-1023";
> +    char *bitsString2 = NULL;
> +    virBitmapPtr bitmap = NULL;
> +    int ret = -1;
> +    int size = 1025;
> +
> +    if (virBitmapParse(bitsString1, 0,&bitmap, size)<  0)
> +        goto error;
> +
> +    if (testBit(bitmap, 1, 32, true)<  0)
> +        goto error;
> +    if (testBit(bitmap, 50, 50, true)<  0)
> +        goto error;
> +    if (testBit(bitmap, 88, 99, true)<  0)
> +        goto error;
> +    if (testBit(bitmap, 1021, 1023, true)<  0)
> +        goto error;
> +
> +    if (testBit(bitmap, 0, 0, false)<  0)
> +        goto error;
> +    if (testBit(bitmap, 33, 49, false)<  0)
> +        goto error;
> +    if (testBit(bitmap, 51, 87, false)<  0)
> +        goto error;
> +    if (testBit(bitmap, 100, 1020, false)<  0)
> +        goto error;
> +
> +    bitsString2 = virBitmapFormat(bitmap);
> +    if (strcmp(bitsString1, bitsString2))
> +        goto error;
> +
> +    virBitmapSetAll(bitmap);
> +    if (testBit(bitmap, 0, size - 1, true)<  0)
> +        goto error;
> +
> +    if (!virBitmapIsAllSet(bitmap))
> +        goto error;
> +
> +    virBitmapClearAll(bitmap);
> +    if (testBit(bitmap, 0, size - 1, false)<  0)
> +        goto error;
> +
> +    ret = 0;
> +
> +error:
> +    virBitmapFree(bitmap);
> +    VIR_FREE(bitsString2);
> +    return ret;
> +}
> +
> +static int test3(const void *data ATTRIBUTE_UNUSED)
> +{
> +    virBitmapPtr bitmap = NULL;
> +    int ret = -1;
> +    int size = 5;
> +    int i;
> +
> +    if ((bitmap = virBitmapNew(size)) == NULL)
> +        goto error;
> +
> +    for (i = 0; i<  size; i++)
> +        ignore_value(virBitmapSetBit(bitmap, i));
> +
> +    if (!virBitmapIsAllSet(bitmap))
> +        goto error;
> +
> +    ret = 0;
> +
> +error:
> +    virBitmapFree(bitmap);
> +    return ret;
> +}
> +
> +/* test for virBitmapNextSetBit */
> +static int test4(const void *data ATTRIBUTE_UNUSED)
> +{
> +    const char *bitsString = "0, 2-4, 6-10, 12, 14-18, 20, 22, 25";
> +    int size = 40;
> +    int bitsPos[] = {
> +        0,  2,  3,  4,  6,  7,  8,  9, 10, 12,
> +        14, 15, 16, 17, 18, 20, 22, 25
> +    };
> +    int npos = 18;
> +    virBitmapPtr bitmap = NULL;
> +    int i, j;
> +
> +    /* 1. zero set */
> +
> +    bitmap = virBitmapNew(size);
> +    if (!bitmap)
> +        goto error;
> +
> +    if (virBitmapNextSetBit(bitmap, -1)>= 0)
> +        goto error;
> +
> +    virBitmapFree(bitmap);
> +    bitmap = NULL;
> +
> +    /* 2. partial set */
> +
> +    if (virBitmapParse(bitsString, 0,&bitmap, size)<  0)
> +        goto error;
> +    if (!bitmap)
> +        goto error;
> +
> +    j = 0;
> +    i = -1;
> +
> +    while (j<  npos) {
> +        i = virBitmapNextSetBit(bitmap, i);
> +        if (i != bitsPos[j++])
> +            goto error;
> +    }
> +
> +    if (virBitmapNextSetBit(bitmap, i)>  0)
> +        goto error;
> +
> +    /* 3. full set */
> +
> +    i = -1;
> +    virBitmapSetAll(bitmap);
> +
> +    for (j = 0; j<  size; j++) {
> +        i = virBitmapNextSetBit(bitmap, i);
> +        if (i != j)
> +            goto error;
> +    }
> +
> +    if (virBitmapNextSetBit(bitmap, i)>  0)
> +        goto error;
> +
> +    virBitmapFree(bitmap);
> +    return 0;
> +
> +error:
> +    virBitmapFree(bitmap);
> +    return -1;
> +}
> +
> +/* test for virBitmapNewData/ToData */
> +static int test5(const void *v ATTRIBUTE_UNUSED)
> +{
> +    char data[] = {0x01, 0x02, 0x00, 0x00};
> +    unsigned char *data2 = NULL;
> +    int len2;
> +    int bits[] = {0, 9};
> +    virBitmapPtr bitmap;
> +    int i, j;
> +    int ret = -1;
> +
> +    bitmap = virBitmapNewData(data, 4);
> +    if (!bitmap)
> +        goto error;
> +
> +    i = 0;
> +    j = -1;
> +    while (i<  sizeof(bits)/sizeof(int)&&
> +           (j = virBitmapNextSetBit(bitmap, j))>= 0) {
> +        if (j != bits[i++])
> +            goto error;
> +    }
> +    if (virBitmapNextSetBit(bitmap, j)>  0)
> +        goto error;
> +
> +    ignore_value(virBitmapSetBit(bitmap, 2));
> +    ignore_value(virBitmapSetBit(bitmap, 15));
> +
> +    if (virBitmapToData(bitmap,&data2,&len2)<  0)
> +        goto error;
> +
> +    if (data2[0] != 0x05 ||
> +        data2[1] != 0x82 ||
> +        data2[2] != 0x00 ||
> +        data2[3] != 0x00)
> +        goto error;
> +
> +    ret = 0;
> +error:
> +    virBitmapFree(bitmap);
> +    VIR_FREE(data2);
> +    return ret;
> +}
> +
> +
> +/* test for virBitmapFormat */
> +static int test6(const void *v ATTRIBUTE_UNUSED)
> +{
> +    virBitmapPtr bitmap = NULL;
> +    char *str = NULL;
> +    int size = 64;
> +    int ret = -1;
> +
> +    bitmap = virBitmapNew(size);
> +    if (!bitmap)
> +        goto error;
> +
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, ""))
> +        goto error;
> +
> +    VIR_FREE(str);
> +
> +    ignore_value(virBitmapSetBit(bitmap, 0));
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, "0"))
> +        goto error;
> +
> +    VIR_FREE(str);
> +
> +    ignore_value(virBitmapSetBit(bitmap, 4));
> +    ignore_value(virBitmapSetBit(bitmap, 5));
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, "0,4-5"))
> +        goto error;
> +
> +    VIR_FREE(str);
> +
> +    ignore_value(virBitmapSetBit(bitmap, 6));
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, "0,4-6"))
> +        goto error;
> +
> +    VIR_FREE(str);
> +
> +    ignore_value(virBitmapSetBit(bitmap, 13));
> +    ignore_value(virBitmapSetBit(bitmap, 14));
> +    ignore_value(virBitmapSetBit(bitmap, 15));
> +    ignore_value(virBitmapSetBit(bitmap, 16));
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, "0,4-6,13-16"))
> +        goto error;
> +
> +    VIR_FREE(str);
> +
> +    ignore_value(virBitmapSetBit(bitmap, 62));
> +    ignore_value(virBitmapSetBit(bitmap, 63));
> +    str = virBitmapFormat(bitmap);
> +    if (!str)
> +        goto error;
> +
> +    if (!STREQ(str, "0,4-6,13-16,62-63"))
> +        goto error;
> +
> +
> +    ret = 0;
> +error:
> +    virBitmapFree(bitmap);
> +    VIR_FREE(str);
> +    return ret;
> +}
> +
> +static int
> +mymain(void)
> +{
> +    int ret = 0;
> +
> +    if (virtTestRun("test1", 1, test1, NULL)<  0)
> +        ret = -1;
> +    if (virtTestRun("test2", 1, test2, NULL)<  0)
> +        ret = -1;
> +    if (virtTestRun("test3", 1, test3, NULL)<  0)
> +        ret = -1;
> +    if (virtTestRun("test4", 1, test4, NULL)<  0)
> +        ret = -1;
> +    if (virtTestRun("test5", 1, test5, NULL)<  0)
> +        ret = -1;
> +    if (virtTestRun("test6", 1, test6, NULL)<  0)
> +        ret = -1;
> +
> +
> +    return ret;
> +}
> +
> +VIRT_TEST_MAIN(mymain)




More information about the libvir-list mailing list