Add new interface for storing json-like objects 34/139334/11
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Wed, 19 Jul 2017 14:09:41 +0000 (16:09 +0200)
committerKonrad Kuchciak <k.kuchciak@samsung.com>
Thu, 3 Aug 2017 13:24:28 +0000 (15:24 +0200)
Change-Id: Ia55546087931d537580020fc1ea6cf36e39a08b3
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
[Use generic functions instead of copy-paste code]
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
src/util/common.c
src/util/common.h

index 01111fce051be3234934547ae925413b4fe9b518..c7bf804db18244751c543dccd372f6f9b5cfdbf9 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <ejdb/bson.h>
 #include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 
@@ -91,3 +92,236 @@ char *bson_get_string(bson *b, char *fieldpath)
 
        return (char *)bson_iterator_string(&it);
 }
+
+static const size_t data_size[] = {
+       [TYPE_OID] = sizeof(faultd_oid_t),
+       [TYPE_STRING] = sizeof(char *),
+       [TYPE_INT] = sizeof(int),
+       [TYPE_TIMESPEC] = sizeof(struct timespec),
+       [TYPE_TIME_T] = sizeof(time_t),
+       [TYPE_UUID] = sizeof(sd_id128_t),
+       [TYPE_OBJECT] = sizeof(struct list_head),
+};
+
+static inline void copy_obj_val(struct faultd_object *obj, void *val)
+{
+       memcpy(&obj->val, val, data_size[obj->type]);
+}
+
+static void release_faultd_object(struct uref *uref)
+{
+       struct faultd_object *obj = container_of(uref, struct faultd_object, uref);
+
+       faultd_object_destroy(obj);
+       free(obj);
+}
+
+static inline void init_obj(struct faultd_object *obj, int type, void *val)
+{
+       assert(val != NULL || type == TYPE_OBJECT);
+
+       obj->type = type;
+       obj->key = NULL;
+       uref_init(&obj->uref, release_faultd_object);
+       INIT_LIST_HEAD(&obj->node);
+
+       if (type == TYPE_OBJECT && val == NULL)
+               INIT_LIST_HEAD(&obj->val.children);
+       else
+               copy_obj_val(obj, val);
+}
+
+static struct faultd_object *new_object_node(int type, void *val)
+{
+       struct faultd_object *obj;
+
+       assert(type >= 0);
+
+       obj = calloc(1, sizeof(*obj));
+       if (!obj)
+               return NULL;
+
+       init_obj(obj, type, val);
+
+       return obj;
+}
+
+int faultd_object_fill_empty(struct faultd_object *obj)
+{
+       return 0;
+}
+
+int faultd_object_new(struct faultd_object **obj)
+{
+       assert(obj);
+
+       *obj = new_object_node(TYPE_OBJECT, NULL);
+       if (!*obj)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void faultd_object_init(struct faultd_object *obj)
+{
+       assert(obj);
+
+       init_obj(obj, TYPE_OBJECT, NULL);
+}
+
+void faultd_object_destroy(struct faultd_object *obj)
+{
+       struct faultd_object *child, *next;
+
+       switch (obj->type) {
+       case TYPE_OBJECT:
+               list_for_each_entry_safe(child, next, &obj->val.children, node) {
+                       list_del_init(&child->node);
+                       faultd_object_unref(child);
+               }
+               break;
+       case TYPE_STRING:
+               free(obj->val.s);
+               break;
+       default:
+               break;
+       };
+
+       free(obj->key);
+}
+
+static int object_append(struct faultd_object *obj, const char *key, struct faultd_object *child)
+{
+       child->key = strdup(key);
+       if (!child->key)
+               return -ENOMEM;
+
+       list_add_tail(&child->node, &obj->val.children);
+       return 0;
+}
+
+int faultd_object_append_new(struct faultd_object *parent, const char *key,
+                                                        int type, void *val)
+{
+       struct faultd_object *child;
+       int ret;
+
+       assert(parent);
+       assert(parent->type == TYPE_OBJECT);
+       assert(key);
+       assert(val);
+
+       child = new_object_node(type, val);
+       if (!child)
+               return -ENOMEM;
+
+       ret = object_append(parent, key, child);
+       if (ret < 0)
+               goto unref_child;
+
+       return 0;
+
+unref_child:
+       faultd_object_unref(child);
+       return ret;
+}
+
+int faultd_object_append_string(struct faultd_object *obj, const char *key, const char *val)
+{
+       char *val_copy;
+       int ret;
+
+       val_copy = strdup(val);
+       if (!val_copy)
+               return -ENOMEM;
+
+       ret = faultd_object_append_new(obj, key, TYPE_STRING, &val_copy);
+       if (ret < 0)
+               goto free_val_copy;
+
+       return 0;
+free_val_copy:
+       free(val_copy);
+       return ret;
+}
+
+int faultd_object_append_object(struct faultd_object *obj, const char *key,
+                                                               struct faultd_object *val)
+{
+       return object_append(obj, key, faultd_object_ref(val));
+}
+
+static struct faultd_object *find_child(struct faultd_object *obj, const char *key)
+{
+       struct faultd_object *child;
+       size_t len;
+       char *dot;
+
+       assert(key);
+
+       dot = strchr(key, '.');
+       if (dot)
+               len = dot - key;
+       else
+               len = strlen(key);
+
+       list_for_each_entry(child, &obj->val.children, node) {
+               if (strncmp(key, child->key, len))
+                       continue;
+
+               if (child->key[len] != '\0')
+                       continue;
+
+               /* is this end of key? */
+               if (!dot)
+                       return child;
+
+               /* Can search we recursively? */
+               if (child->type == TYPE_OBJECT)
+                       return find_child(obj, dot + 1);
+               else
+                       break;
+       }
+
+       return NULL;
+}
+
+int faultd_object_get_val(struct faultd_object *obj, const char *key,
+                                                 int type, void *val)
+{
+       struct faultd_object *child;
+
+       assert(obj);
+       assert(obj->type == TYPE_OBJECT);
+       assert(key);
+
+       child = find_child(obj, key);
+       if (!child)
+               return -ENOENT;
+
+       if (child->type != type)
+               return -EFAULT;
+
+       memcpy(val, &child->val, data_size[child->type]);
+       return 0;
+}
+
+int faultd_object_get_object(struct faultd_object *obj, const char *key, struct faultd_object **val)
+{
+       struct faultd_object *child;
+
+       child = find_child(obj, key);
+       if (!child)
+               return -ENOENT;
+
+       if (child->type != TYPE_OBJECT)
+               return -EFAULT;
+
+       *val = child;
+       return 0;
+}
+
+int faultd_oid_from_string(faultd_oid_t *oid, const char *s)
+{
+       return sd_id128_from_string(s, &oid->uuid);
+}
index 476ea742e8bf7a14af339e79b6dfb00f732de351..2c09c628184683c42e114d63bf2cae23624b69d7 100644 (file)
 #include <stdlib.h>
 #include <time.h>
 #include <errno.h>
+#include <systemd/sd-id128.h>
+
+#include "list.h"
+#include "uref.h"
 
 /*
  * Value taken from linux kernel.
@@ -108,4 +112,140 @@ int bson_fill_empty(bson *b);
 
 char *bson_get_string(bson *b, char *fieldpath);
 
+enum faultd_type {
+       TYPE_OID,
+       TYPE_STRING,
+       TYPE_INT,
+       TYPE_TIMESPEC,
+       TYPE_TIME_T,
+       TYPE_UUID,
+       TYPE_OBJECT,
+};
+
+typedef union {
+       bson_oid_t bson;
+       sd_id128_t uuid;
+} faultd_oid_t;
+
+#define FAULTD_OID_IS_ZERO(o) (o.bson.ints[0] == 0 && \
+                                                        o.bson.ints[1] == 0 && \
+                                                        o.bson.ints[2] == 0)
+
+struct faultd_object {
+       char *key;
+       int type;
+       union {
+               faultd_oid_t oid;
+               char *s;
+               int i;
+               struct timespec ts;
+               time_t time;
+               sd_id128_t uuid;
+               struct list_head children;
+       } val;
+
+       struct uref uref;
+       struct list_head node;
+};
+
+static inline void faultd_object_unref(struct faultd_object *obj)
+{
+       if (!obj)
+               return;
+
+       uref_put(&obj->uref);
+}
+
+static inline struct faultd_object *faultd_object_ref(struct faultd_object *obj)
+{
+       if (!obj)
+               return NULL;
+
+       uref_get(&obj->uref);
+       return obj;
+}
+
+int faultd_object_new(struct faultd_object **obj);
+void faultd_object_init(struct faultd_object *obj);
+void faultd_object_destroy(struct faultd_object *obj);
+
+int faultd_object_append_new(struct faultd_object *parent, const char *key,
+                                                        int type, void *val);
+
+int faultd_object_append_string(struct faultd_object *obj, const char *key,
+                                                               const char *val);
+int faultd_object_append_object(struct faultd_object *obj, const char *key,
+                                                               struct faultd_object *val);
+
+static inline int faultd_object_append_oid(struct faultd_object *obj,
+                                                                                  const char *key, faultd_oid_t *oid)
+{
+       return faultd_object_append_new(obj, key, TYPE_OID, oid);
+}
+
+static inline int faultd_object_append_int(struct faultd_object *obj,
+                                                                                  const char *key, int val)
+{
+       return faultd_object_append_new(obj, key, TYPE_INT, &val);
+}
+
+static inline int faultd_object_append_time_t(struct faultd_object *obj,
+                                                                                         const char *key, time_t val)
+{
+       return faultd_object_append_new(obj, key, TYPE_TIME_T, &val);
+}
+
+static inline int faultd_object_append_timespec(struct faultd_object *obj,
+                                                                                               const char *key,
+                                                                                               struct timespec *val)
+{
+       return faultd_object_append_new(obj, key, TYPE_TIMESPEC, val);
+}
+
+static inline int faultd_object_append_uuid(struct faultd_object *obj,
+                                                                                       const char *key, sd_id128_t *val)
+{
+       return faultd_object_append_new(obj, key, TYPE_UUID, val);
+}
+
+
+int faultd_object_get_val(struct faultd_object *obj, const char *key,
+                                                 int type, void *val);
+
+static inline int faultd_object_get_string(struct faultd_object *obj,
+                                                                                  const char *key, char **val)
+{
+       return faultd_object_get_val(obj, key, TYPE_STRING, val);
+}
+
+static inline int faultd_object_get_int(struct faultd_object *obj,
+                                                                               const char *key, int *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_INT, val);
+}
+
+static inline int faultd_object_get_timespec(struct faultd_object *obj,
+                                                                                        const char *key, struct timespec *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_TIMESPEC, val);
+}
+
+static inline int faultd_object_get_time_t(struct faultd_object *obj,
+                                                                                        const char *key, time_t *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_TIME_T, val);
+}
+
+static inline int faultd_object_get_uuid(struct faultd_object *obj,
+                                                                                const char *key, sd_id128_t *val)
+{
+       return faultd_object_get_val(obj, key, TYPE_UUID, val);
+}
+
+int faultd_object_get_object(struct faultd_object *obj, const char *key, struct faultd_object **val);
+
+int faultd_object_fill_empty(struct faultd_object *obj);
+
+int faultd_oid_from_string(faultd_oid_t *oid, const char *s);
+
 #endif /* FAULTD_COMMON_H */