[Meta] base code for metadata
authorJaeyun <jy1210.jung@samsung.com>
Wed, 20 Jul 2022 08:22:43 +0000 (17:22 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Thu, 4 Aug 2022 11:23:57 +0000 (20:23 +0900)
Add new functions to handle metadata.

Signed-off-by: Jaeyun <jy1210.jung@samsung.com>
src/libnnstreamer-edge/nnstreamer-edge-common.c
src/libnnstreamer-edge/nnstreamer-edge-common.h

index 9ebff0d2e617ea8a646953898707b97961499e0f..75c69bf74ae2da2bb60cf3d0c7708fd175d9679e 100644 (file)
@@ -161,6 +161,280 @@ nns_edge_strdup_printf (const char *format, ...)
   return new_str;
 }
 
+/**
+ * @brief Internal function to find node in the list.
+ */
+static nns_edge_metadata_node_s *
+nns_edge_metadata_find (nns_edge_metadata_s * meta, const char *key)
+{
+  nns_edge_metadata_node_s *node;
+
+  if (!meta)
+    return NULL;
+
+  if (!STR_IS_VALID (key))
+    return NULL;
+
+  node = meta->list;
+  while (node) {
+    if (strcasecmp (key, node->key) == 0)
+      return node;
+
+    node = node->next;
+  }
+
+  return NULL;
+}
+
+/**
+ * @brief Internal function to initialize metadata structure.
+ */
+int
+nns_edge_metadata_init (nns_edge_metadata_s * meta)
+{
+  if (!meta)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  memset (meta, 0, sizeof (nns_edge_metadata_s));
+  return NNS_EDGE_ERROR_NONE;
+}
+
+/**
+ * @brief Internal function to free the list and items in metadata structure.
+ */
+int
+nns_edge_metadata_free (nns_edge_metadata_s * meta)
+{
+  nns_edge_metadata_node_s *node, *tmp;
+
+  if (!meta)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  node = meta->list;
+  meta->list_len = 0;
+  meta->list = NULL;
+
+  while (node) {
+    tmp = node->next;
+
+    SAFE_FREE (node->key);
+    SAFE_FREE (node->value);
+    SAFE_FREE (node);
+
+    node = tmp;
+  }
+
+  return NNS_EDGE_ERROR_NONE;
+}
+
+/**
+ * @brief Internal function to set the metadata.
+ */
+int
+nns_edge_metadata_set (nns_edge_metadata_s * meta,
+    const char *key, const char *value)
+{
+  nns_edge_metadata_node_s *node;
+
+  if (!meta)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  if (!STR_IS_VALID (key))
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  if (!STR_IS_VALID (value))
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  /* Replace old value if key exists in the list. */
+  node = nns_edge_metadata_find (meta, key);
+  if (node) {
+    char *val = nns_edge_strdup (value);
+
+    if (!val)
+      return NNS_EDGE_ERROR_OUT_OF_MEMORY;
+
+    SAFE_FREE (node->value);
+    node->value = val;
+    return NNS_EDGE_ERROR_NONE;
+  }
+
+  node = calloc (1, sizeof (nns_edge_metadata_node_s));
+  if (!node)
+    return NNS_EDGE_ERROR_OUT_OF_MEMORY;
+
+  node->key = nns_edge_strdup (key);
+  node->value = nns_edge_strdup (value);
+
+  if (!node->key || !node->value) {
+    SAFE_FREE (node->key);
+    SAFE_FREE (node->value);
+    SAFE_FREE (node);
+    return NNS_EDGE_ERROR_OUT_OF_MEMORY;
+  }
+
+  /* Prepend new node to the start of the list. */
+  meta->list_len++;
+  node->next = meta->list;
+  meta->list = node;
+
+  return NNS_EDGE_ERROR_NONE;
+}
+
+/**
+ * @brief Internal function to get the metadata in the list. Caller should release the returned value using free().
+ */
+int
+nns_edge_metadata_get (nns_edge_metadata_s * meta,
+    const char *key, char **value)
+{
+  nns_edge_metadata_node_s *node;
+
+  if (!value)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  node = nns_edge_metadata_find (meta, key);
+  if (node) {
+    *value = nns_edge_strdup (node->value);
+    return (*value) ? NNS_EDGE_ERROR_NONE : NNS_EDGE_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NNS_EDGE_ERROR_INVALID_PARAMETER;
+}
+
+/**
+ * @brief Internal function to copy the metadata.
+ */
+int
+nns_edge_metadata_copy (nns_edge_metadata_s * dest, nns_edge_metadata_s * src)
+{
+  nns_edge_metadata_s tmp;
+  nns_edge_metadata_node_s *node;
+  int ret;
+
+  if (!dest || !src)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  nns_edge_metadata_init (&tmp);
+
+  node = src->list;
+  while (node) {
+    ret = nns_edge_metadata_set (&tmp, node->key, node->value);
+    if (ret != NNS_EDGE_ERROR_NONE) {
+      nns_edge_metadata_free (&tmp);
+      return ret;
+    }
+
+    node = node->next;
+  }
+
+  /* Replace dest when new metadata is successfully copied. */
+  nns_edge_metadata_free (dest);
+  *dest = tmp;
+
+  return NNS_EDGE_ERROR_NONE;
+}
+
+/**
+ * @brief Internal function to serialize the metadata. Caller should release the returned value using free().
+ */
+int
+nns_edge_metadata_serialize (nns_edge_metadata_s * meta,
+    void **data, size_t *data_len)
+{
+  nns_edge_metadata_node_s *node;
+  char *serialized, *ptr;
+  size_t total, len;
+
+  if (!meta)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  if (!data || !data_len)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  *data = NULL;
+  *data_len = 0U;
+
+  if (meta->list_len == 0)
+    return NNS_EDGE_ERROR_NONE;
+
+  total = len = sizeof (unsigned int);
+
+  node = meta->list;
+  while (node) {
+    total += (strlen (node->key) + strlen (node->value) + 2);
+    node = node->next;
+  }
+
+  serialized = ptr = (char *) malloc (total);
+  if (!serialized)
+    return NNS_EDGE_ERROR_OUT_OF_MEMORY;
+
+  /* length + list of key-value pair */
+  ((unsigned int *) serialized)[0] = meta->list_len;
+  ptr += len;
+
+  node = meta->list;
+  while (node) {
+    len = strlen (node->key);
+    memcpy (ptr, node->key, len);
+    ptr[len] = '\0';
+    ptr += (len + 1);
+
+    len = strlen (node->value);
+    memcpy (ptr, node->value, len);
+    ptr[len] = '\0';
+    ptr += (len + 1);
+
+    node = node->next;
+  }
+
+  *data = serialized;
+  *data_len = total;
+
+  return NNS_EDGE_ERROR_NONE;
+}
+
+/**
+ * @brief Internal function to deserialize memory into metadata.
+ */
+int
+nns_edge_metadata_deserialize (nns_edge_metadata_s * meta,
+    void *data, size_t data_len)
+{
+  char *key, *value;
+  size_t cur;
+  unsigned int total;
+  int ret;
+
+  if (!meta)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  if (!data || data_len <= 0)
+    return NNS_EDGE_ERROR_INVALID_PARAMETER;
+
+  nns_edge_metadata_free (meta);
+
+  /* length + list of key-value pair */
+  total = ((unsigned int *) data)[0];
+
+  cur = sizeof (unsigned int);
+  while (cur < data_len || meta->list_len < total) {
+    key = (char *) data + cur;
+    cur += (strlen (key) + 1);
+
+    value = (char *) data + cur;
+    cur += (strlen (value) + 1);
+
+    ret = nns_edge_metadata_set (meta, key, value);
+    if (ret != NNS_EDGE_ERROR_NONE) {
+      nns_edge_metadata_free (meta);
+      return ret;
+    }
+  }
+
+  return NNS_EDGE_ERROR_NONE;
+}
+
 /**
  * @brief Create nnstreamer edge event.
  */
index b56e421c0437b0e2209b8ce4f155b3d056311395..1ba441f3577f3a8fe85b934aadb1a878addd08c0 100644 (file)
@@ -45,6 +45,28 @@ extern "C" {
 #define nns_edge_lock(h) do { pthread_mutex_lock (&(h)->lock); } while (0)
 #define nns_edge_unlock(h) do { pthread_mutex_unlock (&(h)->lock); } while (0)
 
+/**
+ * @brief Internal data structure for metadata.
+ */
+typedef struct _nns_edge_metadata_node_s nns_edge_metadata_node_s;
+
+/**
+ * @brief Internal data structure for metadata.
+ */
+struct _nns_edge_metadata_node_s {
+  char *key;
+  char *value;
+  nns_edge_metadata_node_s *next;
+};
+
+/**
+ * @brief Internal data structure to handle metadata. This struct should be managed in the handle.
+ */
+typedef struct {
+  unsigned int list_len;
+  nns_edge_metadata_node_s *list;
+} nns_edge_metadata_s;
+
 /**
  * @brief Internal data structure for raw data.
  */
@@ -182,6 +204,41 @@ char *nns_edge_strndup (const char *str, size_t len);
  */
 char *nns_edge_strdup_printf (const char *format, ...);
 
+/**
+ * @brief Internal function to initialize metadata structure.
+ */
+int nns_edge_metadata_init (nns_edge_metadata_s *meta);
+
+/**
+ * @brief Internal function to free the list and items in metadata structure.
+ */
+int nns_edge_metadata_free (nns_edge_metadata_s *meta);
+
+/**
+ * @brief Internal function to set the metadata.
+ */
+int nns_edge_metadata_set (nns_edge_metadata_s *meta, const char *key, const char *value);
+
+/**
+ * @brief Internal function to get the metadata in the list. Caller should release the returned value using free().
+ */
+int nns_edge_metadata_get (nns_edge_metadata_s *meta, const char *key, char **value);
+
+/**
+ * @brief Internal function to copy the metadata.
+ */
+int nns_edge_metadata_copy (nns_edge_metadata_s *dest, nns_edge_metadata_s *src);
+
+/**
+ * @brief Internal function to serialize the metadata. Caller should release the returned value using free().
+ */
+int nns_edge_metadata_serialize (nns_edge_metadata_s *meta, void **data, size_t *data_len);
+
+/**
+ * @brief Internal function to deserialize memory into metadata.
+ */
+int nns_edge_metadata_deserialize (nns_edge_metadata_s *meta, void *data, size_t data_len);
+
 /**
  * @brief Create nnstreamer edge event.
  * @note This is internal function for edge event.