[libvirt] [PATCH 18/28] Rename sexpr.{c,h} to virsexpr.{c,h}

Daniel P. Berrange berrange at redhat.com
Mon Dec 17 14:57:51 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

---
 cfg.mk                  |   2 +-
 po/POTFILES.in          |   2 +-
 src/Makefile.am         |   2 +-
 src/util/sexpr.c        | 625 ------------------------------------------------
 src/util/sexpr.h        |  58 -----
 src/util/virsexpr.c     | 625 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virsexpr.h     |  58 +++++
 src/xen/xend_internal.c |   2 +-
 src/xenxs/xen_sxpr.h    |   2 +-
 src/xenxs/xen_xm.c      |   2 +-
 10 files changed, 689 insertions(+), 689 deletions(-)
 delete mode 100644 src/util/sexpr.c
 delete mode 100644 src/util/sexpr.h
 create mode 100644 src/util/virsexpr.c
 create mode 100644 src/util/virsexpr.h

diff --git a/cfg.mk b/cfg.mk
index e23f1c5..0a66797 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -807,7 +807,7 @@ exclude_file_name_regexp--sc_prohibit_sprintf = \
 exclude_file_name_regexp--sc_prohibit_strncpy = ^src/util/util\.c$$
 
 exclude_file_name_regexp--sc_prohibit_strtol = \
-  ^src/(util/sexpr|(vbox|xen|xenxs)/.*)\.c$$
+  ^src/(util/virsexpr|(vbox|xen|xenxs)/.*)\.c$$
 
 exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/xml\.c$$
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fb73807..2b09531 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -138,7 +138,6 @@ src/test/test_driver.c
 src/uml/uml_conf.c
 src/uml/uml_driver.c
 src/util/iohelper.c
-src/util/sexpr.c
 src/util/stats_linux.c
 src/util/storage_file.c
 src/util/sysinfo.c
@@ -173,6 +172,7 @@ src/util/virpci.c
 src/util/virpidfile.c
 src/util/virprocess.c
 src/util/virrandom.c
+src/util/virsexpr.c
 src/util/virsocketaddr.c
 src/util/virterror.c
 src/util/virterror_internal.h
diff --git a/src/Makefile.am b/src/Makefile.am
index c0e35dc..c0dfd38 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,7 +53,6 @@ augeastest_DATA =
 # These files are not related to driver APIs. Simply generic
 # helper APIs for various purposes
 UTIL_SOURCES =							\
-		util/sexpr.c util/sexpr.h			\
 		util/stats_linux.c util/stats_linux.h		\
 		util/storage_file.c util/storage_file.h		\
 		util/sysinfo.c util/sysinfo.h			\
@@ -86,6 +85,7 @@ UTIL_SOURCES =							\
 		util/virpci.c util/virpci.h			\
 		util/virpidfile.c util/virpidfile.h		\
 		util/virprocess.c util/virprocess.h		\
+		util/virsexpr.c util/virsexpr.h			\
 		util/virtypedparam.c util/virtypedparam.h	\
 		util/xml.c util/xml.h				\
 		util/virterror.c util/virterror_internal.h	\
diff --git a/src/util/sexpr.c b/src/util/sexpr.c
deleted file mode 100644
index ae0cc18..0000000
--- a/src/util/sexpr.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * sexpr.c : S-Expression routines to communicate with the Xen Daemon
- *
- * Copyright (C) 2010-2011 Red Hat, Inc.
- * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING.LIB in the main directory of this
- *  archive for more details.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "c-ctype.h"
-#include <errno.h>
-
-#include "virterror_internal.h"
-#include "sexpr.h"
-#include "util.h"
-#include "viralloc.h"
-
-#define VIR_FROM_THIS VIR_FROM_SEXPR
-
-
-/**
- * sexpr_new:
- *
- * Create a new S-Expression
- *
- * Returns the new node or NULL in case of memory allocation error
- */
-static struct sexpr *
-sexpr_new(void)
-{
-    struct sexpr *ret;
-
-    if (VIR_ALLOC(ret) < 0) {
-        virReportOOMError();
-        return NULL;
-    }
-    ret->kind = SEXPR_NIL;
-    return ret;
-}
-
-/**
- * sexpr_free:
- * @sexpr: the S-Expression pointer
- *
- * Free an S-Expression
- */
-void
-sexpr_free(struct sexpr *sexpr)
-{
-    int serrno = errno;
-
-    if (sexpr == NULL) {
-        return;
-    }
-
-    switch (sexpr->kind) {
-        case SEXPR_CONS:
-            sexpr_free(sexpr->u.s.car);
-            sexpr_free(sexpr->u.s.cdr);
-            break;
-        case SEXPR_VALUE:
-            VIR_FREE(sexpr->u.value);
-            break;
-        case SEXPR_NIL:
-            break;
-    }
-
-    VIR_FREE(sexpr);
-
-    errno = serrno;
-}
-
-/**
- * sexpr_nil:
- *
- * Provide a NIL S-Expression (the pointer is not shared so NIL equality
- * testing won't work at the pointer level).
- *
- * Returns a new NIL S-Expression of NULL in case of error.
- */
-struct sexpr *
-sexpr_nil(void)
-{
-    return sexpr_new();
-}
-
-/**
- * sexpr_string:
- * @str:  the input string, assumed to be UTF-8
- * @len:  the length in bytes of the input
- *
- * Parse the input S-Expression and return a pointer to the result
- *
- * Returns the S-Expression pointer or NULL in case of error
- */
-struct sexpr *
-sexpr_string(const char *str, ssize_t len)
-{
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return ret;
-    ret->kind = SEXPR_VALUE;
-    if (len > 0) {
-        ret->u.value = strndup(str, len);
-    } else {
-        ret->u.value = strdup(str);
-    }
-
-    if (ret->u.value == NULL) {
-        VIR_FREE(ret);
-        return NULL;
-    }
-
-    return ret;
-}
-
-/**
- * sexpr_cons:
- * @car: the left operand
- * @cdr: the right operand
- *
- * Implement the CONS operation assembling 2 existing S-Expressions.
- * Note that in case of error the input data are not freed.
- *
- * Returns the resulting S-Expression pointer or NULL in case of error.
- */
-struct sexpr *
-sexpr_cons(const struct sexpr *car, const struct sexpr *cdr)
-{
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return ret;
-    ret->kind = SEXPR_CONS;
-    ret->u.s.car = (struct sexpr *) car;
-    ret->u.s.cdr = (struct sexpr *) cdr;
-
-    return ret;
-}
-
-/**
- * append:
- * @lst: an existing list
- * @value: the value
- *
- * Internal operation appending a value at the end of an existing list
- */
-static int
-append(struct sexpr *lst, const struct sexpr *value)
-{
-    struct sexpr *nil = sexpr_nil();
-
-    if (nil == NULL)
-        return -1;
-
-    while (lst->kind != SEXPR_NIL) {
-        lst = lst->u.s.cdr;
-    }
-
-    lst->kind = SEXPR_CONS;
-    lst->u.s.car = (struct sexpr *) value;
-    lst->u.s.cdr = nil;
-
-    return 0;
-}
-
-/**
- * @lst: an existing list
- * @value: the value
- *
- * Append a value at the end of an existing list
- *
- * Returns lst or NULL in case of error
- */
-struct sexpr *
-sexpr_append(struct sexpr *lst, const struct sexpr *value)
-{
-    if (lst == NULL)
-        return NULL;
-    if (value == NULL)
-        return lst;
-    if (append(lst, value) < 0)
-        return NULL;
-    return lst;
-}
-
-/**
- * sexpr2string:
- * @sexpr: an S-Expression pointer
- * @buffer: the output buffer
- *
- * Serialize the S-Expression in the buffer.
- *
- * Returns 0 on success, -1 on error.
- */
-int
-sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer)
-{
-    if ((sexpr == NULL) || (buffer == NULL))
-        return -1;
-
-    switch (sexpr->kind) {
-    case SEXPR_CONS:
-        virBufferAddChar(buffer, '(');
-
-        if (sexpr2string(sexpr->u.s.car, buffer) < 0)
-            return -1;
-
-        while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
-            sexpr = sexpr->u.s.cdr;
-
-            virBufferAddChar(buffer, ' ');
-
-            if (sexpr2string(sexpr->u.s.car, buffer) < 0)
-                return -1;
-        }
-
-        virBufferAddChar(buffer, ')');
-        break;
-    case SEXPR_VALUE:
-        if (strchr(sexpr->u.value, ' ') ||
-            strchr(sexpr->u.value, ')') ||
-            strchr(sexpr->u.value, '('))
-            virBufferAsprintf(buffer, "'%s'", sexpr->u.value);
-        else
-            virBufferAdd(buffer, sexpr->u.value, -1);
-
-        break;
-    case SEXPR_NIL:
-        virBufferAddLit(buffer, "()");
-        break;
-    default:
-        virReportError(VIR_ERR_SEXPR_SERIAL,
-                       _("unknown s-expression kind %d"), sexpr->kind);
-        return -1;
-    }
-
-    return 0;
-}
-
-#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
-
-static const char *
-trim(const char *string)
-{
-    while (IS_SPACE(*string))
-        string++;
-    return string;
-}
-
-/**
- * _string2sexpr:
- * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
- * @end: pointer to an index in the buffer for the already parsed bytes
- *
- * Internal routine implementing the parse of S-Expression
- * Note that failure in this function is catastrophic.  If it returns
- * NULL, you've leaked memory and you're currently OOM.  It will always
- * parse an SEXPR given a buffer
- *
- * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
- *         hard error.
- */
-static struct sexpr *
-_string2sexpr(const char *buffer, size_t * end)
-{
-    const char *ptr = buffer + *end;
-    struct sexpr *ret = sexpr_new();
-
-    if (ret == NULL)
-        return NULL;
-
-    ptr = trim(ptr);
-
-    if (ptr[0] == '(') {
-        ret->kind = SEXPR_NIL;
-
-        ptr = trim(ptr + 1);
-        while (*ptr && *ptr != ')') {
-            struct sexpr *tmp;
-            size_t tmp_len = 0;
-
-            tmp = _string2sexpr(ptr, &tmp_len);
-            if (tmp == NULL)
-                goto error;
-            if (append(ret, tmp) < 0) {
-                sexpr_free(tmp);
-                goto error;
-            }
-            ptr = trim(ptr + tmp_len);
-        }
-
-        if (*ptr == ')') {
-            ptr++;
-        }
-    } else {
-        const char *start;
-
-        if (*ptr == '\'') {
-            ptr++;
-            start = ptr;
-
-            while (*ptr && *ptr != '\'') {
-                if (*ptr == '\\' && ptr[1])
-                    ptr++;
-                ptr++;
-            }
-
-            ret->u.value = strndup(start, ptr - start);
-            if (ret->u.value == NULL) {
-                virReportOOMError();
-                goto error;
-            }
-
-            if (*ptr == '\'')
-                ptr++;
-        } else {
-            start = ptr;
-
-            while (*ptr && !c_isspace(*ptr)
-                   && *ptr != ')' && *ptr != '(') {
-                ptr++;
-            }
-
-            ret->u.value = strndup(start, ptr - start);
-            if (ret->u.value == NULL) {
-                virReportOOMError();
-                goto error;
-            }
-        }
-
-        ret->kind = SEXPR_VALUE;
-        if (ret->u.value == NULL)
-            goto error;
-    }
-
-    *end = ptr - buffer;
-
-    return ret;
-
-  error:
-    sexpr_free(ret);
-    return NULL;
-}
-
-/**
- * string2sexpr:
- * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
- *
- * Parse the S-Expression in the buffer.
- * Note that failure in this function is catastrophic.  If it returns
- * NULL, you've leaked memory and you're currently OOM.  It will always
- * parse an SEXPR given a buffer
- *
- * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
- *         hard error.
- */
-struct sexpr *
-string2sexpr(const char *buffer)
-{
-    size_t dummy = 0;
-
-    return _string2sexpr(buffer, &dummy);
-}
-
-
-/**
- * sexpr_lookup_key:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path
- * Returns the key node, rather than the data node.
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the pointer to the sub expression or NULL if not found.
- */
-static struct sexpr *
-sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *result = NULL;
-    char *buffer, *ptr, *token;
-
-    if ((node == NULL) || (sexpr == NULL))
-        return NULL;
-
-    buffer = strdup(node);
-
-    if (buffer == NULL) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    ptr = buffer;
-    token = strsep(&ptr, "/");
-
-    if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
-        goto cleanup;
-    }
-
-    if (STRNEQ(sexpr->u.s.car->u.value, token)) {
-        goto cleanup;
-    }
-
-    for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
-        const struct sexpr *i;
-
-        sexpr = sexpr->u.s.cdr;
-        for (i = sexpr; i->kind != SEXPR_NIL; i = i->u.s.cdr) {
-            if (i->kind != SEXPR_CONS ||
-                i->u.s.car->kind != SEXPR_CONS ||
-                i->u.s.car->u.s.car->kind != SEXPR_VALUE) {
-                continue;
-            }
-
-            if (STREQ(i->u.s.car->u.s.car->u.value, token)) {
-                sexpr = i->u.s.car;
-                break;
-            }
-        }
-
-        if (i->kind == SEXPR_NIL) {
-            break;
-        }
-    }
-
-    if (token != NULL) {
-        goto cleanup;
-    }
-
-    result = (struct sexpr *) sexpr;
-
-cleanup:
-    VIR_FREE(buffer);
-
-    return result;
-}
-
-/**
- * sexpr_lookup:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path.
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the pointer to the sub expression or NULL if not found.
- */
-struct sexpr *
-sexpr_lookup(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *s = sexpr_lookup_key(sexpr, node);
-
-    if (s == NULL)
-        return NULL;
-
-    if (s->kind != SEXPR_CONS || s->u.s.cdr->kind != SEXPR_CONS)
-        return NULL;
-
-    return s->u.s.cdr;
-}
-
-/**
- * sexpr_has:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the sub expression to lookup in the S-Expression
- *
- * Search a sub expression in the S-Expression based on its path.
- * NOTE: path are limited to 4096 bytes.
- * NB, even if the key was found sexpr_lookup may return NULL if
- * the corresponding value was empty
- *
- * Returns true if the key was found, false otherwise
- */
-int
-sexpr_has(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *s = sexpr_lookup_key(sexpr, node);
-
-    if (s == NULL)
-        return 0;
-
-    if (s->kind != SEXPR_CONS)
-        return 0;
-
-    return 1;
-}
-
-/**
- * sexpr_node:
- * @sexpr: a pointer to a parsed S-Expression
- * @node: a path for the node to lookup in the S-Expression
- *
- * Search a node value in the S-Expression based on its path
- * NOTE: path are limited to 4096 bytes.
- *
- * Returns the value of the node or NULL if not found.
- */
-const char *
-sexpr_node(const struct sexpr *sexpr, const char *node)
-{
-    struct sexpr *n = sexpr_lookup(sexpr, node);
-
-    return (n && n->u.s.car->kind == SEXPR_VALUE) ? n->u.s.car->u.value : NULL;
-}
-
-int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst)
-{
-    const char *val = sexpr_node(sexpr, node);
-
-    if (val && *val) {
-        *dst = strdup(val);
-        if (!(*dst))
-            return -1;
-    } else {
-        *dst = NULL;
-    }
-    return 0;
-}
-
-
-/**
- * sexpr_fmt_node:
- * @sexpr: a pointer to a parsed S-Expression
- * @fmt: a path for the node to lookup in the S-Expression
- * @... extra data to build the path
- *
- * Search a node value in the S-Expression based on its path
- *
- * Returns the value of the node or NULL if not found.
- */
-const char *
-sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
-{
-    int result;
-    va_list ap;
-    char *node;
-    const char *value;
-
-    va_start(ap, fmt);
-    result = virVasprintf(&node, fmt, ap);
-    va_end(ap);
-
-    if (result < 0) {
-        return NULL;
-    }
-
-    value = sexpr_node(sexpr, node);
-
-    VIR_FREE(node);
-
-    return value;
-}
-
-/**
- * sexpr_int:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup an int value in the S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error).
- * This function suffers from the flaw that zero is both a correct
- * return value and an error indicator: careful!
- */
-int
-sexpr_int(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtol(value, NULL, 0);
-    }
-    return 0;
-}
-
-
-/**
- * sexpr_float:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a float value in the S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-double
-sexpr_float(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtod(value, NULL);
-    }
-    return 0;
-}
-
-/**
- * sexpr_u64:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a 64bits unsigned int value in the
- * S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-uint64_t
-sexpr_u64(const struct sexpr *sexpr, const char *name)
-{
-    const char *value = sexpr_node(sexpr, name);
-
-    if (value) {
-        return strtoll(value, NULL, 0);
-    }
-    return 0;
-}
diff --git a/src/util/sexpr.h b/src/util/sexpr.h
deleted file mode 100644
index 13ec481..0000000
--- a/src/util/sexpr.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
- *
- * Copyright (C) 2012 Red Hat, Inc.
- * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
- *
- *  This file is subject to the terms and conditions of the GNU Lesser General
- *  Public License. See the file COPYING.LIB in the main directory of this
- *  archive for more details.
- */
-
-#ifndef _LIBVIR_SEXPR_H_
-# define _LIBVIR_SEXPR_H_
-
-# include "internal.h"
-# include "virbuffer.h"
-
-enum sexpr_type {
-    SEXPR_NIL,
-    SEXPR_CONS,
-    SEXPR_VALUE,
-};
-
-struct sexpr {
-    enum sexpr_type kind;
-    union {
-        struct {
-            struct sexpr *car;
-            struct sexpr *cdr;
-        } s;
-        char *value;
-    } u;
-};
-
-/* conversion to/from strings */
-int sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer);
-struct sexpr *string2sexpr(const char *buffer);
-
-/* constructors and destructors */
-struct sexpr *sexpr_nil(void);
-struct sexpr *sexpr_string(const char *str, ssize_t len);
-struct sexpr *sexpr_cons(const struct sexpr *car, const struct sexpr *cdr);
-struct sexpr *sexpr_append(struct sexpr *lst, const struct sexpr *item);
-void sexpr_free(struct sexpr *sexpr);
-
-/* lookup in S-Expressions */
-const char *sexpr_node(const struct sexpr *sexpr, const char *node);
-int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst);
-const char *sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
-  ATTRIBUTE_FMT_PRINTF(2,3);
-struct sexpr *sexpr_lookup(const struct sexpr *sexpr, const char *node);
-int sexpr_has(const struct sexpr *sexpr, const char *node);
-
-int sexpr_int(const struct sexpr *sexpr, const char *name);
-double sexpr_float(const struct sexpr *sexpr, const char *name);
-uint64_t sexpr_u64(const struct sexpr *sexpr, const char *name);
-
-#endif
diff --git a/src/util/virsexpr.c b/src/util/virsexpr.c
new file mode 100644
index 0000000..80c24c4
--- /dev/null
+++ b/src/util/virsexpr.c
@@ -0,0 +1,625 @@
+/*
+ * sexpr.c : S-Expression routines to communicate with the Xen Daemon
+ *
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING.LIB in the main directory of this
+ *  archive for more details.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "c-ctype.h"
+#include <errno.h>
+
+#include "virterror_internal.h"
+#include "virsexpr.h"
+#include "util.h"
+#include "viralloc.h"
+
+#define VIR_FROM_THIS VIR_FROM_SEXPR
+
+
+/**
+ * sexpr_new:
+ *
+ * Create a new S-Expression
+ *
+ * Returns the new node or NULL in case of memory allocation error
+ */
+static struct sexpr *
+sexpr_new(void)
+{
+    struct sexpr *ret;
+
+    if (VIR_ALLOC(ret) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+    ret->kind = SEXPR_NIL;
+    return ret;
+}
+
+/**
+ * sexpr_free:
+ * @sexpr: the S-Expression pointer
+ *
+ * Free an S-Expression
+ */
+void
+sexpr_free(struct sexpr *sexpr)
+{
+    int serrno = errno;
+
+    if (sexpr == NULL) {
+        return;
+    }
+
+    switch (sexpr->kind) {
+        case SEXPR_CONS:
+            sexpr_free(sexpr->u.s.car);
+            sexpr_free(sexpr->u.s.cdr);
+            break;
+        case SEXPR_VALUE:
+            VIR_FREE(sexpr->u.value);
+            break;
+        case SEXPR_NIL:
+            break;
+    }
+
+    VIR_FREE(sexpr);
+
+    errno = serrno;
+}
+
+/**
+ * sexpr_nil:
+ *
+ * Provide a NIL S-Expression (the pointer is not shared so NIL equality
+ * testing won't work at the pointer level).
+ *
+ * Returns a new NIL S-Expression of NULL in case of error.
+ */
+struct sexpr *
+sexpr_nil(void)
+{
+    return sexpr_new();
+}
+
+/**
+ * sexpr_string:
+ * @str:  the input string, assumed to be UTF-8
+ * @len:  the length in bytes of the input
+ *
+ * Parse the input S-Expression and return a pointer to the result
+ *
+ * Returns the S-Expression pointer or NULL in case of error
+ */
+struct sexpr *
+sexpr_string(const char *str, ssize_t len)
+{
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return ret;
+    ret->kind = SEXPR_VALUE;
+    if (len > 0) {
+        ret->u.value = strndup(str, len);
+    } else {
+        ret->u.value = strdup(str);
+    }
+
+    if (ret->u.value == NULL) {
+        VIR_FREE(ret);
+        return NULL;
+    }
+
+    return ret;
+}
+
+/**
+ * sexpr_cons:
+ * @car: the left operand
+ * @cdr: the right operand
+ *
+ * Implement the CONS operation assembling 2 existing S-Expressions.
+ * Note that in case of error the input data are not freed.
+ *
+ * Returns the resulting S-Expression pointer or NULL in case of error.
+ */
+struct sexpr *
+sexpr_cons(const struct sexpr *car, const struct sexpr *cdr)
+{
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return ret;
+    ret->kind = SEXPR_CONS;
+    ret->u.s.car = (struct sexpr *) car;
+    ret->u.s.cdr = (struct sexpr *) cdr;
+
+    return ret;
+}
+
+/**
+ * append:
+ * @lst: an existing list
+ * @value: the value
+ *
+ * Internal operation appending a value at the end of an existing list
+ */
+static int
+append(struct sexpr *lst, const struct sexpr *value)
+{
+    struct sexpr *nil = sexpr_nil();
+
+    if (nil == NULL)
+        return -1;
+
+    while (lst->kind != SEXPR_NIL) {
+        lst = lst->u.s.cdr;
+    }
+
+    lst->kind = SEXPR_CONS;
+    lst->u.s.car = (struct sexpr *) value;
+    lst->u.s.cdr = nil;
+
+    return 0;
+}
+
+/**
+ * @lst: an existing list
+ * @value: the value
+ *
+ * Append a value at the end of an existing list
+ *
+ * Returns lst or NULL in case of error
+ */
+struct sexpr *
+sexpr_append(struct sexpr *lst, const struct sexpr *value)
+{
+    if (lst == NULL)
+        return NULL;
+    if (value == NULL)
+        return lst;
+    if (append(lst, value) < 0)
+        return NULL;
+    return lst;
+}
+
+/**
+ * sexpr2string:
+ * @sexpr: an S-Expression pointer
+ * @buffer: the output buffer
+ *
+ * Serialize the S-Expression in the buffer.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer)
+{
+    if ((sexpr == NULL) || (buffer == NULL))
+        return -1;
+
+    switch (sexpr->kind) {
+    case SEXPR_CONS:
+        virBufferAddChar(buffer, '(');
+
+        if (sexpr2string(sexpr->u.s.car, buffer) < 0)
+            return -1;
+
+        while (sexpr->u.s.cdr->kind != SEXPR_NIL) {
+            sexpr = sexpr->u.s.cdr;
+
+            virBufferAddChar(buffer, ' ');
+
+            if (sexpr2string(sexpr->u.s.car, buffer) < 0)
+                return -1;
+        }
+
+        virBufferAddChar(buffer, ')');
+        break;
+    case SEXPR_VALUE:
+        if (strchr(sexpr->u.value, ' ') ||
+            strchr(sexpr->u.value, ')') ||
+            strchr(sexpr->u.value, '('))
+            virBufferAsprintf(buffer, "'%s'", sexpr->u.value);
+        else
+            virBufferAdd(buffer, sexpr->u.value, -1);
+
+        break;
+    case SEXPR_NIL:
+        virBufferAddLit(buffer, "()");
+        break;
+    default:
+        virReportError(VIR_ERR_SEXPR_SERIAL,
+                       _("unknown s-expression kind %d"), sexpr->kind);
+        return -1;
+    }
+
+    return 0;
+}
+
+#define IS_SPACE(c) ((c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA))
+
+static const char *
+trim(const char *string)
+{
+    while (IS_SPACE(*string))
+        string++;
+    return string;
+}
+
+/**
+ * _string2sexpr:
+ * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
+ * @end: pointer to an index in the buffer for the already parsed bytes
+ *
+ * Internal routine implementing the parse of S-Expression
+ * Note that failure in this function is catastrophic.  If it returns
+ * NULL, you've leaked memory and you're currently OOM.  It will always
+ * parse an SEXPR given a buffer
+ *
+ * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
+ *         hard error.
+ */
+static struct sexpr *
+_string2sexpr(const char *buffer, size_t * end)
+{
+    const char *ptr = buffer + *end;
+    struct sexpr *ret = sexpr_new();
+
+    if (ret == NULL)
+        return NULL;
+
+    ptr = trim(ptr);
+
+    if (ptr[0] == '(') {
+        ret->kind = SEXPR_NIL;
+
+        ptr = trim(ptr + 1);
+        while (*ptr && *ptr != ')') {
+            struct sexpr *tmp;
+            size_t tmp_len = 0;
+
+            tmp = _string2sexpr(ptr, &tmp_len);
+            if (tmp == NULL)
+                goto error;
+            if (append(ret, tmp) < 0) {
+                sexpr_free(tmp);
+                goto error;
+            }
+            ptr = trim(ptr + tmp_len);
+        }
+
+        if (*ptr == ')') {
+            ptr++;
+        }
+    } else {
+        const char *start;
+
+        if (*ptr == '\'') {
+            ptr++;
+            start = ptr;
+
+            while (*ptr && *ptr != '\'') {
+                if (*ptr == '\\' && ptr[1])
+                    ptr++;
+                ptr++;
+            }
+
+            ret->u.value = strndup(start, ptr - start);
+            if (ret->u.value == NULL) {
+                virReportOOMError();
+                goto error;
+            }
+
+            if (*ptr == '\'')
+                ptr++;
+        } else {
+            start = ptr;
+
+            while (*ptr && !c_isspace(*ptr)
+                   && *ptr != ')' && *ptr != '(') {
+                ptr++;
+            }
+
+            ret->u.value = strndup(start, ptr - start);
+            if (ret->u.value == NULL) {
+                virReportOOMError();
+                goto error;
+            }
+        }
+
+        ret->kind = SEXPR_VALUE;
+        if (ret->u.value == NULL)
+            goto error;
+    }
+
+    *end = ptr - buffer;
+
+    return ret;
+
+  error:
+    sexpr_free(ret);
+    return NULL;
+}
+
+/**
+ * string2sexpr:
+ * @buffer: a zero terminated buffer containing an S-Expression in UTF-8
+ *
+ * Parse the S-Expression in the buffer.
+ * Note that failure in this function is catastrophic.  If it returns
+ * NULL, you've leaked memory and you're currently OOM.  It will always
+ * parse an SEXPR given a buffer
+ *
+ * Returns a pointer to the resulting parsed S-Expression, or NULL in case of
+ *         hard error.
+ */
+struct sexpr *
+string2sexpr(const char *buffer)
+{
+    size_t dummy = 0;
+
+    return _string2sexpr(buffer, &dummy);
+}
+
+
+/**
+ * sexpr_lookup_key:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path
+ * Returns the key node, rather than the data node.
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the pointer to the sub expression or NULL if not found.
+ */
+static struct sexpr *
+sexpr_lookup_key(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *result = NULL;
+    char *buffer, *ptr, *token;
+
+    if ((node == NULL) || (sexpr == NULL))
+        return NULL;
+
+    buffer = strdup(node);
+
+    if (buffer == NULL) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    ptr = buffer;
+    token = strsep(&ptr, "/");
+
+    if (sexpr->kind != SEXPR_CONS || sexpr->u.s.car->kind != SEXPR_VALUE) {
+        goto cleanup;
+    }
+
+    if (STRNEQ(sexpr->u.s.car->u.value, token)) {
+        goto cleanup;
+    }
+
+    for (token = strsep(&ptr, "/"); token; token = strsep(&ptr, "/")) {
+        const struct sexpr *i;
+
+        sexpr = sexpr->u.s.cdr;
+        for (i = sexpr; i->kind != SEXPR_NIL; i = i->u.s.cdr) {
+            if (i->kind != SEXPR_CONS ||
+                i->u.s.car->kind != SEXPR_CONS ||
+                i->u.s.car->u.s.car->kind != SEXPR_VALUE) {
+                continue;
+            }
+
+            if (STREQ(i->u.s.car->u.s.car->u.value, token)) {
+                sexpr = i->u.s.car;
+                break;
+            }
+        }
+
+        if (i->kind == SEXPR_NIL) {
+            break;
+        }
+    }
+
+    if (token != NULL) {
+        goto cleanup;
+    }
+
+    result = (struct sexpr *) sexpr;
+
+cleanup:
+    VIR_FREE(buffer);
+
+    return result;
+}
+
+/**
+ * sexpr_lookup:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path.
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the pointer to the sub expression or NULL if not found.
+ */
+struct sexpr *
+sexpr_lookup(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *s = sexpr_lookup_key(sexpr, node);
+
+    if (s == NULL)
+        return NULL;
+
+    if (s->kind != SEXPR_CONS || s->u.s.cdr->kind != SEXPR_CONS)
+        return NULL;
+
+    return s->u.s.cdr;
+}
+
+/**
+ * sexpr_has:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the sub expression to lookup in the S-Expression
+ *
+ * Search a sub expression in the S-Expression based on its path.
+ * NOTE: path are limited to 4096 bytes.
+ * NB, even if the key was found sexpr_lookup may return NULL if
+ * the corresponding value was empty
+ *
+ * Returns true if the key was found, false otherwise
+ */
+int
+sexpr_has(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *s = sexpr_lookup_key(sexpr, node);
+
+    if (s == NULL)
+        return 0;
+
+    if (s->kind != SEXPR_CONS)
+        return 0;
+
+    return 1;
+}
+
+/**
+ * sexpr_node:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @node: a path for the node to lookup in the S-Expression
+ *
+ * Search a node value in the S-Expression based on its path
+ * NOTE: path are limited to 4096 bytes.
+ *
+ * Returns the value of the node or NULL if not found.
+ */
+const char *
+sexpr_node(const struct sexpr *sexpr, const char *node)
+{
+    struct sexpr *n = sexpr_lookup(sexpr, node);
+
+    return (n && n->u.s.car->kind == SEXPR_VALUE) ? n->u.s.car->u.value : NULL;
+}
+
+int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst)
+{
+    const char *val = sexpr_node(sexpr, node);
+
+    if (val && *val) {
+        *dst = strdup(val);
+        if (!(*dst))
+            return -1;
+    } else {
+        *dst = NULL;
+    }
+    return 0;
+}
+
+
+/**
+ * sexpr_fmt_node:
+ * @sexpr: a pointer to a parsed S-Expression
+ * @fmt: a path for the node to lookup in the S-Expression
+ * @... extra data to build the path
+ *
+ * Search a node value in the S-Expression based on its path
+ *
+ * Returns the value of the node or NULL if not found.
+ */
+const char *
+sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
+{
+    int result;
+    va_list ap;
+    char *node;
+    const char *value;
+
+    va_start(ap, fmt);
+    result = virVasprintf(&node, fmt, ap);
+    va_end(ap);
+
+    if (result < 0) {
+        return NULL;
+    }
+
+    value = sexpr_node(sexpr, node);
+
+    VIR_FREE(node);
+
+    return value;
+}
+
+/**
+ * sexpr_int:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup an int value in the S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error).
+ * This function suffers from the flaw that zero is both a correct
+ * return value and an error indicator: careful!
+ */
+int
+sexpr_int(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtol(value, NULL, 0);
+    }
+    return 0;
+}
+
+
+/**
+ * sexpr_float:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup a float value in the S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error)
+ */
+double
+sexpr_float(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtod(value, NULL);
+    }
+    return 0;
+}
+
+/**
+ * sexpr_u64:
+ * @sexpr: an S-Expression
+ * @name: the name for the value
+ *
+ * convenience function to lookup a 64bits unsigned int value in the
+ * S-Expression
+ *
+ * Returns the value found or 0 if not found (but may not be an error)
+ */
+uint64_t
+sexpr_u64(const struct sexpr *sexpr, const char *name)
+{
+    const char *value = sexpr_node(sexpr, name);
+
+    if (value) {
+        return strtoll(value, NULL, 0);
+    }
+    return 0;
+}
diff --git a/src/util/virsexpr.h b/src/util/virsexpr.h
new file mode 100644
index 0000000..13ec481
--- /dev/null
+++ b/src/util/virsexpr.h
@@ -0,0 +1,58 @@
+/*
+ * sexpr.h : S-Expression interfaces needed to communicate with the Xen Daemon
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005 Anthony Liguori <aliguori at us.ibm.com>
+ *
+ *  This file is subject to the terms and conditions of the GNU Lesser General
+ *  Public License. See the file COPYING.LIB in the main directory of this
+ *  archive for more details.
+ */
+
+#ifndef _LIBVIR_SEXPR_H_
+# define _LIBVIR_SEXPR_H_
+
+# include "internal.h"
+# include "virbuffer.h"
+
+enum sexpr_type {
+    SEXPR_NIL,
+    SEXPR_CONS,
+    SEXPR_VALUE,
+};
+
+struct sexpr {
+    enum sexpr_type kind;
+    union {
+        struct {
+            struct sexpr *car;
+            struct sexpr *cdr;
+        } s;
+        char *value;
+    } u;
+};
+
+/* conversion to/from strings */
+int sexpr2string(const struct sexpr *sexpr, virBufferPtr buffer);
+struct sexpr *string2sexpr(const char *buffer);
+
+/* constructors and destructors */
+struct sexpr *sexpr_nil(void);
+struct sexpr *sexpr_string(const char *str, ssize_t len);
+struct sexpr *sexpr_cons(const struct sexpr *car, const struct sexpr *cdr);
+struct sexpr *sexpr_append(struct sexpr *lst, const struct sexpr *item);
+void sexpr_free(struct sexpr *sexpr);
+
+/* lookup in S-Expressions */
+const char *sexpr_node(const struct sexpr *sexpr, const char *node);
+int sexpr_node_copy(const struct sexpr *sexpr, const char *node, char **dst);
+const char *sexpr_fmt_node(const struct sexpr *sexpr, const char *fmt, ...)
+  ATTRIBUTE_FMT_PRINTF(2,3);
+struct sexpr *sexpr_lookup(const struct sexpr *sexpr, const char *node);
+int sexpr_has(const struct sexpr *sexpr, const char *node);
+
+int sexpr_int(const struct sexpr *sexpr, const char *name);
+double sexpr_float(const struct sexpr *sexpr, const char *name);
+uint64_t sexpr_u64(const struct sexpr *sexpr, const char *name);
+
+#endif
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index a4005f4..6e8bc2f 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -35,7 +35,7 @@
 #include "xend_internal.h"
 #include "driver.h"
 #include "util.h"
-#include "sexpr.h"
+#include "virsexpr.h"
 #include "xen_sxpr.h"
 #include "virbuffer.h"
 #include "uuid.h"
diff --git a/src/xenxs/xen_sxpr.h b/src/xenxs/xen_sxpr.h
index 4ff640c..d7ce46a 100644
--- a/src/xenxs/xen_sxpr.h
+++ b/src/xenxs/xen_sxpr.h
@@ -30,7 +30,7 @@
 # include "internal.h"
 # include "virconf.h"
 # include "domain_conf.h"
-# include "sexpr.h"
+# include "virsexpr.h"
 
 typedef enum {
     XEND_CONFIG_VERSION_3_0_2 = 1,
diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c
index 7d67bbe..c29df1c 100644
--- a/src/xenxs/xen_xm.c
+++ b/src/xenxs/xen_xm.c
@@ -31,7 +31,7 @@
 #include "viralloc.h"
 #include "verify.h"
 #include "uuid.h"
-#include "sexpr.h"
+#include "virsexpr.h"
 #include "count-one-bits.h"
 #include "xenxs_private.h"
 #include "xen_xm.h"
-- 
1.7.11.7




More information about the libvir-list mailing list