]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: massive cleanup
authorAdam Sutton <dev@adamsutton.me.uk>
Tue, 11 Jun 2013 19:18:04 +0000 (20:18 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Tue, 11 Jun 2013 19:18:04 +0000 (20:18 +0100)
I've cleaned up all the methods to make things a bit more consistent and
removed stuff that wasn't being used.

src/idnode.c
src/idnode.h
src/prop.c
src/prop.h

index e8f356d5a1ca478f3781d6b9fa4e8a45e9c2009c..7952d0ad4a4baba27ca2fd2155b660dad27c8851 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ *  Tvheadend - idnode (class) system
+ *
+ *  Copyright (C) 2013 Andreas Öman
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "notify.h"
 #include "settings.h"
 
-static int randfd = 0;
+static int              randfd = 0;
+static RB_HEAD(,idnode) idnodes;
 
-RB_HEAD(idnode_tree, idnode);
+static void idnode_updated(idnode_t *in, int optmask);
 
-static struct idnode_tree idnodes;
+/* **************************************************************************
+ * Utilities
+ * *************************************************************************/
 
 /**
  *
@@ -71,29 +93,30 @@ bin2hex(char *dst, size_t dstlen, const uint8_t *src, size_t srclen)
   *dst = 0;
 }
 
-
 /**
  *
  */
-void
-idnode_init(void)
+static int
+in_cmp(const idnode_t *a, const idnode_t *b)
 {
-  randfd = open("/dev/urandom", O_RDONLY);
-  if(randfd == -1)
-    exit(1);
+  return memcmp(a->in_uuid, b->in_uuid, 16);
 }
 
+/* **************************************************************************
+ * Registration
+ * *************************************************************************/
 
 /**
  *
  */
-static int
-in_cmp(const idnode_t *a, const idnode_t *b)
+void
+idnode_init(void)
 {
-  return memcmp(a->in_uuid, b->in_uuid, 16);
+  randfd = open("/dev/urandom", O_RDONLY);
+  if(randfd == -1)
+    exit(1);
 }
 
-
 /**
  *
  */
@@ -121,45 +144,6 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class)
   return 0;
 }
 
-
-/**
- *
- */
-const char *
-idnode_uuid_as_str(const idnode_t *in)
-{
-  static char ret[16][33];
-  static int p;
-  char *b = ret[p];
-  bin2hex(b, 33, in->in_uuid, 16);
-  p = (p + 1) & 15;
-  return b;
-}
-
-
-/**
- *
- */
-void *
-idnode_find(const char *uuid, const idclass_t *idc)
-{
-  idnode_t skel, *r;
-
-  if(hex2bin(skel.in_uuid, 16, uuid))
-    return NULL;
-  r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
-  if(r != NULL && idc != NULL) {
-    const idclass_t *c = r->in_class;
-    for(;c != NULL; c = c->ic_super) {
-      if(idc == c)
-        return r;
-    }
-    return NULL;
-  }
-  return r;
-}
-
-
 /**
  *
  */
@@ -169,28 +153,24 @@ idnode_unlink(idnode_t *in)
   RB_REMOVE(&idnodes, in, in_link);
 }
 
+/* **************************************************************************
+ * Info
+ * *************************************************************************/
 
 /**
- * Recursive to get superclass nodes first
+ *
  */
-static void
-add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p)
+const char *
+idnode_uuid_as_str(const idnode_t *in)
 {
-  if(ic->ic_super != NULL)
-    add_params(self, ic->ic_super, p);
-
-  if(TAILQ_FIRST(&p->hm_fields) != NULL) {
-    // Only add separator if not empty
-    htsmsg_t *m = htsmsg_create_map();
-    htsmsg_add_str(m, "caption", ic->ic_caption ?: ic->ic_class);
-    htsmsg_add_str(m, "type", "separator");
-    htsmsg_add_msg(p, NULL, m);
-  }
-
-  prop_add_params_to_msg(self, ic->ic_properties, p);
+  static char ret[16][33];
+  static int p;
+  char *b = ret[p];
+  bin2hex(b, 33, in->in_uuid, 16);
+  p = (p + 1) & 15;
+  return b;
 }
 
-
 /**
  *
  */
@@ -209,7 +189,7 @@ idnode_get_title(idnode_t *in)
 /**
  *
  */
-idnode_t **
+idnode_set_t *
 idnode_get_childs(idnode_t *in)
 {
   if(in == NULL)
@@ -223,7 +203,6 @@ idnode_get_childs(idnode_t *in)
   return NULL;
 }
 
-
 /**
  *
  */
@@ -231,8 +210,6 @@ int
 idnode_is_leaf(idnode_t *in)
 {
   const idclass_t *ic = in->in_class;
-  if(ic->ic_leaf)
-    return 1;
   for(; ic != NULL; ic = ic->ic_super) {
     if(ic->ic_get_childs != NULL)
       return 0;
@@ -240,137 +217,9 @@ idnode_is_leaf(idnode_t *in)
   return 1;
 }
 
-
-
-/**
- *
- */
-htsmsg_t *
-idnode_serialize(struct idnode *self)
-{
-  const idclass_t *c = self->in_class;
-  htsmsg_t *m;
-  if(c->ic_serialize != NULL) {
-    m = c->ic_serialize(self);
-  } else {
-    m = htsmsg_create_map();
-    htsmsg_add_str(m, "id", idnode_uuid_as_str(self));
-    htsmsg_add_str(m, "text", idnode_get_title(self));
-
-    htsmsg_t *p  = htsmsg_create_list();
-    add_params(self, c, p);
-
-    htsmsg_add_msg(m, "params", p);
-
-  }
-  return m;
-}
-
-/**
- *
- */
-static void
-idnode_updated(idnode_t *in)
-{
-  const idclass_t *ic = in->in_class;
-
-  for(; ic != NULL; ic = ic->ic_super) {
-    if(ic->ic_save != NULL) {
-      ic->ic_save(in);
-      break;
-    }
-  }
-
-  // Tell about updated parameters
-
-  htsmsg_t *m = htsmsg_create_map();
-  htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
-
-  htsmsg_t *p  = htsmsg_create_list();
-  add_params(in, in->in_class, p);
-  htsmsg_add_msg(m, "params", p);
-
-  notify_by_msg("idnodeParamsChanged", m);
-}
-
-
-/**
- *
- */
-void
-idnode_set_prop(idnode_t *in, const char *key, const char *value)
-{
-  const idclass_t *ic = in->in_class;
-  int do_save = 0;
-  for(;ic != NULL; ic = ic->ic_super) {
-    int x = prop_set(in, ic->ic_properties, key, value);
-    if(x == -1)
-      continue;
-    do_save |= x;
-    break;
-  }
-  if(do_save)
-    idnode_updated(in);
-}
-
-
-/**
- *
- */
-void
-idnode_update_all_props(idnode_t *in,
-                        const char *(*getvalue)(void *opaque, const char *key),
-                        void *opaque)
-{
-  const idclass_t *ic = in->in_class;
-  int do_save = 0;
-  for(;ic != NULL; ic = ic->ic_super)
-    do_save |= prop_update_all(in, ic->ic_properties, getvalue, opaque);
-  if(do_save)
-    idnode_updated(in);
-}
-
-
-/**
- *
- */
-void
-idnode_notify_title_changed(void *obj)
-{
-  idnode_t *in = obj;
-  htsmsg_t *m = htsmsg_create_map();
-  htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
-  htsmsg_add_str(m, "text", idnode_get_title(in));
-  notify_by_msg("idnodeNameChanged", m);
-}
-
-/*
- * Save
- */
-void
-idnode_save ( idnode_t *self, htsmsg_t *c )
-{
-  const idclass_t *idc = self->in_class;
-  while (idc) {
-    prop_read_values(self, idc->ic_properties, c);
-    idc = idc->ic_super;
-  }
-}
-
-/*
- * Load
- */
-void
-idnode_load ( idnode_t *self, htsmsg_t *c, int dosave )
-{
-  const idclass_t *idc = self->in_class;
-  while (idc) {
-    prop_write_values(self, idc->ic_properties, c);
-    idc = idc->ic_super;
-  }
-  if (dosave)
-    idnode_updated(self);
-}
+/* **************************************************************************
+ * Properties
+ * *************************************************************************/
 
 static const property_t *
 idnode_find_prop
@@ -408,6 +257,9 @@ idnode_get_str
   return NULL;
 }
 
+/*
+ * Get field as unsigned int
+ */
 int
 idnode_get_u32
   ( idnode_t *self, const char *key, uint32_t *u32 )
@@ -433,8 +285,75 @@ idnode_get_u32
   return 1;
 }
 
+/*
+ * Get field as BOOL
+ */
+int
+idnode_get_bool
+  ( idnode_t *self, const char *key, int *b )
+{
+  const property_t *p = idnode_find_prop(self, key);
+  if (p) {
+    void *ptr = self;
+    ptr += p->off;
+    switch (p->type) {
+      case PT_BOOL:
+        *b = *(int*)ptr;
+        return 0;
+      default:
+        break;
+    }
+  }
+  return 1; 
+}
+
 /* **************************************************************************
- * Set procsesing
+ * Lookup
+ * *************************************************************************/
+
+/**
+ *
+ */
+void *
+idnode_find(const char *uuid, const idclass_t *idc)
+{
+  idnode_t skel, *r;
+
+  if(hex2bin(skel.in_uuid, 16, uuid))
+    return NULL;
+  r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
+  if(r != NULL && idc != NULL) {
+    const idclass_t *c = r->in_class;
+    for(;c != NULL; c = c->ic_super) {
+      if(idc == c)
+        return r;
+    }
+    return NULL;
+  }
+  return r;
+}
+
+idnode_set_t *
+idnode_find_all ( const idclass_t *idc )
+{
+  idnode_t *in;
+  const idclass_t *ic;
+  idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
+  RB_FOREACH(in, &idnodes, in_link) {
+    ic = in->in_class;
+    while (ic) {
+      if (ic == idc) {
+        idnode_set_add(is, in, NULL);
+        break;
+      }
+      ic = ic->ic_super;
+    }
+  }
+  return is;
+}
+
+/* **************************************************************************
+ * Set processing
  * *************************************************************************/
 
 static int
@@ -626,21 +545,140 @@ idnode_set_free ( idnode_set_t *is )
   free(is);
 }
 
-idnode_set_t *
-idnode_find_all ( const idclass_t *idc )
+/* **************************************************************************
+ * Write
+ * *************************************************************************/
+
+int
+idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
 {
-  idnode_t *in;
-  const idclass_t *ic;
-  idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
-  RB_FOREACH(in, &idnodes, in_link) {
-    ic = in->in_class;
-    while (ic) {
-      if (ic == idc) {
-        idnode_set_add(is, in, NULL);
-        break;
-      }
-      ic = ic->ic_super;
+  int save = 0;
+  const idclass_t *idc = self->in_class;
+  for (; idc; idc = idc->ic_super)
+    save |= prop_write_values(self, idc->ic_properties, c, optmask);
+  if (save && dosave)
+    idnode_updated(self, optmask);
+  return save;
+}
+
+/* **************************************************************************
+ * Read
+ * *************************************************************************/
+
+/*
+ * Save
+ */
+void
+idnode_read0 ( idnode_t *self, htsmsg_t *c, int optmask )
+{
+  const idclass_t *idc = self->in_class;
+  for (; idc; idc = idc->ic_super)
+    prop_read_values(self, idc->ic_properties, c, optmask);
+}
+
+/**
+ * Recursive to get superclass nodes first
+ */
+static void
+add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p, int optmask)
+{
+  /* Parent first */
+  if(ic->ic_super != NULL)
+    add_params(self, ic->ic_super, p, optmask);
+
+  /* Seperator (if not empty) */
+  if(TAILQ_FIRST(&p->hm_fields) != NULL) {
+    htsmsg_t *m = htsmsg_create_map();
+    htsmsg_add_str(m, "caption",  ic->ic_caption ?: ic->ic_class);
+    htsmsg_add_str(m, "type",     "separator");
+    htsmsg_add_msg(p, NULL, m);
+  }
+
+  /* Properties */
+  prop_serialize(self, ic->ic_properties, p, optmask);
+}
+
+static htsmsg_t *
+idnode_params (const idclass_t *idc, idnode_t *self, int optmask)
+{
+  htsmsg_t *p  = htsmsg_create_list();
+  add_params(self, idc, p, optmask);
+  return p;
+}
+
+/*
+ * Just get the class definition
+ */
+htsmsg_t *
+idclass_serialize0(const idclass_t *idc, int optmask)
+{
+  return idnode_params(idc, NULL, optmask);
+}
+
+/**
+ *
+ */
+htsmsg_t *
+idnode_serialize0(idnode_t *self, int optmask)
+{
+  const idclass_t *idc = self->in_class;
+
+  htsmsg_t *m = htsmsg_create_map();
+  htsmsg_add_str(m, "uuid", idnode_uuid_as_str(self));
+  htsmsg_add_str(m, "text", idnode_get_title(self));
+
+  htsmsg_add_msg(m, "params", idnode_params(idc, self, optmask));
+
+  return m;
+}
+
+/* **************************************************************************
+ * Notifcation
+ * *************************************************************************/
+
+/**
+ *
+ */
+static void
+idnode_updated(idnode_t *in, int optmask)
+{
+  const idclass_t *ic = in->in_class;
+
+  /* Save */
+  for(; ic != NULL; ic = ic->ic_super) {
+    if(ic->ic_save != NULL) {
+      ic->ic_save(in);
+      break;
     }
   }
-  return is;
+
+  /* Notification */
+
+  htsmsg_t *m = htsmsg_create_map();
+  htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
+
+  htsmsg_t *p  = htsmsg_create_list();
+  add_params(in, in->in_class, p, optmask);
+  htsmsg_add_msg(m, "params", p);
+
+  notify_by_msg("idnodeParamsChanged", m);
+}
+
+/**
+ *
+ */
+void
+idnode_notify_title_changed(void *obj)
+{
+  idnode_t *in = obj;
+  htsmsg_t *m = htsmsg_create_map();
+  htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
+  htsmsg_add_str(m, "text", idnode_get_title(in));
+  notify_by_msg("idnodeNameChanged", m);
 }
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
index 947a0a315bcf4222d054b5085c1c53ef2aa5703a..5e6f40f07be2f409d92086c76cbd4b865579e6ca 100644 (file)
@@ -1,4 +1,24 @@
-#pragma once
+/*
+ *  Tvheadend - idnode (class) system
+ *
+ *  Copyright (C) 2013 Andreas Öman
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TVH_IDNODE_H__
+#define __TVH_IDNODE_H__
 
 #include "tvheadend.h"
 #include "prop.h"
 #include <regex.h>
 
 struct htsmsg;
-struct idnode;
+typedef struct idnode idnode_t;
+
+/*
+ * Node set
+ */
+typedef struct idnode_set
+{
+  idnode_t **is_array;  ///< Array of nodes
+  size_t     is_alloc;  ///< Size of is_array
+  size_t     is_count;  ///< Current usage of is_array
+} idnode_set_t;
 
+/*
+ * Class definition
+ */
 typedef struct idclass {
-  const struct idclass *ic_super;
-  const char *ic_class;
-  const char *ic_caption;
-  int ic_leaf;
-  struct htsmsg *(*ic_serialize)(struct idnode *self);
-  struct idnode **(*ic_get_childs)(struct idnode *self);
-  const char *(*ic_get_title)(struct idnode *self);
-  void (*ic_save)(struct idnode *self);
-  const property_t *ic_properties;
+  const struct idclass  *ic_super;      /// Parent class
+  const char            *ic_class;      /// Class name
+  const char            *ic_caption;    /// Class description
+  const property_t      *ic_properties; /// Property list
+
+  /* Callbacks */
+  idnode_set_t   *(*ic_get_childs)(idnode_t *self);
+  const char     *(*ic_get_title) (idnode_t *self);
+  void            (*ic_save)      (idnode_t *self);
 } idclass_t;
 
+/*
+ * Node definition
+ */
+struct idnode {
+  uint8_t           in_uuid[16];  ///< Unique ID
+  RB_ENTRY(idnode)  in_link;      ///< Global hash 
+  const idclass_t  *in_class;     ///< Class definition
+};
 
-typedef struct idnode {
-  uint8_t in_uuid[16];
-  RB_ENTRY(idnode) in_link;
-  const idclass_t *in_class;
-} idnode_t;
-
+/*
+ * Sorting definition
+ */
 typedef struct idnode_sort {
-  const char *key;
+  const char *key;  ///< Sort key
   enum {
     IS_ASC,
     IS_DSC
-  }           dir;
+  }           dir;  ///< Sort direction
 } idnode_sort_t;
 
+/*
+ * Filter definition
+ */
 typedef struct idnode_filter_ele
 {
-  LIST_ENTRY(idnode_filter_ele) link;
-  char *key;
+  LIST_ENTRY(idnode_filter_ele) link; ///< List link
+
+  char *key;                          ///< Filter key
   enum {
     IF_STR,
     IF_NUM,
     IF_BOOL
-  } type;
+  } type;                             ///< Filter type
   union {
     int      b;
     char    *s;
     int64_t  n;
     regex_t  re;
-  } u;
+  } u;                                ///< Filter data
   enum {
-    IC_EQ, // Equals
-    IC_LT, // LT
-    IC_GT, // GT
-    IC_IN, // contains (STR only)
-    IC_RE, // regexp (STR only)
-  } comp;
+    IC_EQ, ///< Equals
+    IC_LT, ///< LT
+    IC_GT, ///< GT
+    IC_IN, ///< contains (STR only)
+    IC_RE, ///< regexp (STR only)
+  } comp;                             ///< Filter comparison
 } idnode_filter_ele_t;
 
 typedef LIST_HEAD(,idnode_filter_ele) idnode_filter_t;
 
-typedef struct idnode_set
-{
-  idnode_t **is_array;
-  size_t     is_alloc;
-  size_t     is_count;
-} idnode_set_t;
-
 void idnode_init(void);
 
-int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
-
-const char *idnode_uuid_as_str(const idnode_t *in);
-
-void *idnode_find(const char *uuid, const idclass_t *class);
-
-idnode_set_t *idnode_find_all(const idclass_t *class);
-
-idnode_t **idnode_get_childs(idnode_t *in);
-
-int idnode_is_leaf(idnode_t *in);
-
+int  idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
 void idnode_unlink(idnode_t *in);
 
-htsmsg_t *idnode_serialize(struct idnode *self);
-
-void idnode_set_prop(idnode_t *in, const char *key, const char *value);
-
-const property_t* idnode_get_prop(idnode_t *in, const char *key);
+const char   *idnode_uuid_as_str  (const idnode_t *in);
+idnode_set_t *idnode_get_childs   (idnode_t *in);
+int           idnode_is_leaf      (idnode_t *in);
 
-void idnode_update_all_props(idnode_t *in,
-                             const char *(*getvalue)(void *opaque,
-                                                     const char *key),
-                             void *opaque);
+void         *idnode_find    (const char *uuid, const idclass_t *class);
+idnode_set_t *idnode_find_all(const idclass_t *class);
 
 void idnode_notify_title_changed(void *obj);
 
-void idnode_save ( idnode_t *self, htsmsg_t *m );
-void idnode_load ( idnode_t *self, htsmsg_t *m, int dosave );
+htsmsg_t *idclass_serialize0 (const idclass_t *idc, int optmask);
+htsmsg_t *idnode_serialize0  (idnode_t *self, int optmask);
+void      idnode_read0  (idnode_t *self, htsmsg_t *m, int optmask);
+int       idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave);
 
-const char *idnode_get_str ( idnode_t *self, const char *key );
-int idnode_get_u32(idnode_t *self, const char *key, uint32_t *u32);
-int idnode_get_bool(idnode_t *self, const char *key, int *b);
+#define idclass_serialize(idc) idclass_serialize0(idc, 0)
+#define idnode_serialize(in)   idnode_serialize0(in, 0)
+#define idnode_load(in, m)     idnode_write0(in, m, PO_NOSAVE, 0)
+#define idnode_save(in, m)     idnode_read0(in, m, PO_NOSAVE)
+#define idnode_update(in, m)   idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1)
+
+const char *idnode_get_str (idnode_t *self, const char *key );
+int         idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
+int         idnode_get_bool(idnode_t *self, const char *key, int *b);
 
-/*
- * Set processing
- */
 void idnode_filter_add_str
   (idnode_filter_t *f, const char *k, const char *v, int t);
 void idnode_filter_add_num
@@ -117,7 +142,16 @@ void idnode_filter_clear
   (idnode_filter_t *f);
 int  idnode_filter
   ( idnode_t *in, idnode_filter_t *filt );
+#define idnode_set_create() calloc(1, sizeof(idnode_set_t))
 void idnode_set_add
   ( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt );
 void idnode_set_sort    ( idnode_set_t *is, idnode_sort_t *s );
 void idnode_set_free    ( idnode_set_t *is );
+
+#endif /* __TVH_IDNODE_H__ */
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
index 5d5216164b9a45dd5095ef7070c715e9151ba054..21c200cd4c46665bb4f849356c2efc4f4ecc84b5 100644 (file)
@@ -1,16 +1,38 @@
+/*
+ *  Tvheadend - property system (part of idnode)
+ *
+ *  Copyright (C) 2013 Andreas Öman
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #include <stdio.h>
 #include <string.h>
 
 #include "tvheadend.h"
 #include "prop.h"
 
+/* **************************************************************************
+ * Utilities
+ * *************************************************************************/
 
+#define TO_FROM(x, y) ((x) << 16 | (y))
 
-
-
-/**
- *
+/*
+ * Bool conversion
  */
+#if 0
 static int
 str_to_bool(const char *s)
 {
@@ -25,6 +47,18 @@ str_to_bool(const char *s)
     return 1;
   return 0;
 }
+#endif
+
+/**
+ *
+ */
+const static struct strtab typetab[] = {
+  { "bool",  PT_BOOL },
+  { "int",   PT_INT },
+  { "str",   PT_STR },
+  { "u16",   PT_U16 },
+  { "u32",   PT_U32 },
+};
 
 
 const property_t *
@@ -37,65 +71,109 @@ prop_find(const property_t *p, const char *id)
   return NULL;
 }
 
-
-
-#define TO_FROM(x, y) ((x) << 16 | (y))
+/* **************************************************************************
+ * Write
+ * *************************************************************************/
 
 /**
  *
  */
-void
-prop_write_values(void *obj, const property_t *pl, htsmsg_t *m)
+int
+prop_write_values(void *obj, const property_t *pl, htsmsg_t *m, int optmask)
 {
+  int save = 0;
   htsmsg_field_t *f;
   HTSMSG_FOREACH(f, m) {
     if(f->hmf_name == NULL)
       continue;
+
+    /* Find Property */
     const property_t *p = prop_find(pl, f->hmf_name);
     if(p == NULL) {
-      //fprintf(stderr, "Property %s unmappable\n", f->hmf_name);
+      tvhwarn("prop", "invalid property %s", f->hmf_name);
       continue;
     }
-    if(p->options & PO_NOSAVE) continue;
+    
+    /* Ignore */
+    if(p->opts & optmask) continue;
 
-    void *val = obj + p->off;
+    /* Write */
+    void *v = obj + p->off;
     switch(TO_FROM(p->type, f->hmf_type)) {
-    case TO_FROM(PT_BOOL, HMF_BOOL):
-      *(int *)val = f->hmf_bool;
+    case TO_FROM(PT_BOOL, HMF_BOOL): {
+      int *val = v;
+      if (*val != f->hmf_bool) {
+        *val = f->hmf_bool;
+        save = 1;
+      }
       break;
-    case TO_FROM(PT_BOOL, HMF_S64):
-      *(int *)val = !!f->hmf_s64;
+    }
+    case TO_FROM(PT_BOOL, HMF_S64): {
+      int *val = v;
+      if (*val != !!f->hmf_s64) {
+        *val = !!f->hmf_s64;
+        save = 1;
+      }
       break;
-    case TO_FROM(PT_INT, HMF_S64):
-      *(int *)val = f->hmf_s64;
+    }
+    case TO_FROM(PT_INT, HMF_S64): {
+      int *val = v;
+      if (*val != f->hmf_s64) {
+        *val = f->hmf_s64;
+        save = 1;
+      }
       break;
-    case TO_FROM(PT_U16, HMF_S64):
-      *(uint16_t *)val = f->hmf_s64;
+    }
+    case TO_FROM(PT_U16, HMF_S64): {
+      uint16_t *val = v;
+      if (*val != f->hmf_s64) {
+        *val = f->hmf_s64;
+        save = 1;
+      }
       break;
-    case TO_FROM(PT_U32, HMF_S64):
-      *(uint32_t *)val = f->hmf_s64;
+    }
+    case TO_FROM(PT_U32, HMF_S64): {
+      uint32_t *val = v;
+      if (*val != f->hmf_s64) {
+        *val = f->hmf_s64;
+        save = 1;
+      }
       break;
-    case TO_FROM(PT_STR, HMF_STR):
+    }
+    case TO_FROM(PT_STR, HMF_STR): {
+      char **val = v;
       if(p->str_set != NULL)
-        p->str_set(obj, f->hmf_str);
-      else
-        mystrset(val, f->hmf_str);
+        save |= p->str_set(obj, f->hmf_str);
+      else if (!strcmp(*val ?: "", f->hmf_str)) {
+        free(*val);
+        *val = strdup(f->hmf_str);
+        save = 1;
+      }
       break;
     }
+    }
   }
+  return save;
 }
 
-
+/* **************************************************************************
+ * Read
+ * *************************************************************************/
 
 /**
  *
  */
 static void
-prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name)
+prop_read_value
+  (void *obj, const property_t *p, htsmsg_t *m, const char *name, int optmask)
 {
   const char *s;
   const void *val = obj + p->off;
 
+  /* Ignore */
+  if (p->opts & optmask) return;
+
+  /* Read */
   switch(p->type) {
   case PT_BOOL:
     htsmsg_add_bool(m, name, *(int *)val);
@@ -125,147 +203,52 @@ prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name)
  *
  */
 void
-prop_read_values(void *obj, const property_t *p, htsmsg_t *m)
+prop_read_values(void *obj, const property_t *pl, htsmsg_t *m, int optmask)
 {
-  if(p == NULL)
+  if(pl == NULL)
     return;
-  int i = 0;
-  for(;p[i].id; i++)
-    prop_read_value(obj, p+i, m, p[i].id);
+  for (; pl->id; pl++)
+    prop_read_value(obj, pl, m, pl->id, optmask);
 }
 
-
-/**
- *
- */
-const static struct strtab typetab[] = {
-  { "bool",  PT_BOOL },
-  { "int",   PT_INT },
-  { "str",   PT_STR },
-  { "u16",   PT_U16 },
-  { "u32",   PT_U32 },
-};
-
-
 /**
  *
  */
 void
-prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg)
+prop_serialize(void *obj, const property_t *pl, htsmsg_t *msg, int optmask)
 {
-  if(p == NULL)
+  if(pl == NULL)
     return;
-  int i = 0;
-  for(;p[i].id; i++) {
+
+  for(; pl->id; pl++) {
     htsmsg_t *m = htsmsg_create_map();
-    htsmsg_add_str(m, "id", p[i].id);
-    htsmsg_add_str(m, "caption", p[i].name);
-    htsmsg_add_str(m, "type", val2str(p[i].type, typetab) ?: "unknown");
-    if (p->options & PO_RDONLY)
-      htsmsg_add_u32(m, "rdonly", 1);
-    if (p->options & PO_NOSAVE)
-      htsmsg_add_u32(m, "nosave", 1);
-    if (p[i].type == PT_STR && p[i].str_enum) {
-      htsmsg_t *l    = htsmsg_create_list();
-      const char **e = p[i].str_enum(obj);
-      while (*e) {
-        htsmsg_add_str(l, NULL, *e);
-        e++;
-      }
-      htsmsg_add_msg(m, "enum", l);
-    } else if (p[i].type == PT_STR && p[i].str_enum2) {
-      htsmsg_add_msg(m, "enum", p[i].str_enum2(obj));
-    }
-    if (obj)
-      prop_read_value(obj, p+i, m, "value");
     htsmsg_add_msg(msg, NULL, m);
-  }
-}
 
+    /* Metadata */
+    htsmsg_add_str(m, "id",       pl->id);
+    htsmsg_add_str(m, "caption",  pl->name);
+    htsmsg_add_str(m, "type",     val2str(pl->type, typetab) ?: "unknown");
 
-/**
- * value can be NULL
- *
- * Return 1 if we actually changed something
- */
-static int
-prop_seti(void *obj, const property_t *p, const char *value)
-{
-  int i;
-  uint32_t u32;
-  uint16_t u16;
-  const char *s;
-
-  if (p->options & PO_NOSAVE) return 0;
-
-  void *val = obj + p->off;
-  switch(p->type) {
-
-  case PT_BOOL:
-    i = str_to_bool(value);
-    if(0)
-  case PT_INT:
-    i = value ? atoi(value) : 0;
-    if(*(int *)val == i)
-      return 0; // Already set
-    *(int *)val = i;
-    break;
-  case PT_U16:
-    u16 = value ? atoi(value) : 0;
-    if(*(uint16_t *)val == u16)
-      return 0;
-    *(uint16_t *)val = u16;
-    break;
-  case PT_U32:
-    u32 = value ? atoi(value) : 0;
-    if(*(uint32_t *)val == u32)
-      return 0;
-    *(uint32_t *)val = u32;
-    break;
-  case PT_STR:
-    if(p->str_get != NULL)
-      s = p->str_get(obj);
-    else
-      s = *(const char **)val;
+    /* Options */
+    if (pl->opts & PO_RDONLY)
+      htsmsg_add_u32(m, "rdonly", 1);
+    if (pl->opts & PO_NOSAVE)
+      htsmsg_add_u32(m, "nosave", 1);
+    if (pl->opts & PO_WRONCE)
+      htsmsg_add_u32(m, "wronce", 1);
 
-    if(!strcmp(s ?: "", value ?: ""))
-      return 0;
+    /* Enum list */
+    if (pl->str_enum)
+      htsmsg_add_msg(m, "enum", pl->str_enum(obj));
 
-    if(p->str_set != NULL)
-      p->str_set(obj, value);
-    else
-      mystrset(val, value);
-    break;
+    /* Data */
+    if (obj)
+      prop_read_value(obj, pl, m, "value", optmask);
   }
-  if(p->notify)
-    p->notify(obj);
-  return 1;
-}
-
-
-/**
- * Return 1 if something changed
- */
-int
-prop_set(void *obj, const property_t *p, const char *key, const char *value)
-{
-  if((p = prop_find(p, key)) == NULL)
-    return -1;
-  return prop_seti(obj, p, value);
 }
 
-
-/**
+/******************************************************************************
+ * Editor Configuration
  *
- */
-int
-prop_update_all(void *obj, const property_t *p,
-                const char *(*getvalue)(void *opaque, const char *key),
-                void *opaque)
-{
-  int i = 0;
-  int r = 0;
-  for(; p[i].id; i++)
-    r |= prop_seti(obj, p+i, getvalue(opaque, p[i].id));
-  return r;
-}
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
index 83c2fdca19ec3c992e67d2ae6d24c770e5703b12..a9e1ce984a3fb6e61e29338581b735557402269c 100644 (file)
@@ -1,8 +1,32 @@
-#pragma once
+/*
+ *  Tvheadend - property system (part of idnode)
+ *
+ *  Copyright (C) 2013 Andreas Öman
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TVH_PROP_H__
+#define __TVH_PROP_H__
+
 #include <stddef.h>
 
 #include "htsmsg.h"
 
+/*
+ * Property types
+ */
 typedef enum {
   PT_BOOL,
   PT_STR,
@@ -11,64 +35,51 @@ typedef enum {
   PT_U32,
 } prop_type_t;
 
-#define PO_NONE   0x0
-#define PO_RDONLY 0x1 // Note: if this is changed, change PROPDEF2
-#define PO_NOSAVE 0x2
-#define PO_WRONCE 0x4
-
+/*
+ * Property options
+ */
+#define PO_NONE   0x00
+#define PO_RDONLY 0x01  // Property is read-only 
+#define PO_NOSAVE 0x02  // Property is transient (not saved)
+#define PO_WRONCE 0x04  // Property is write-once (i.e. on creation)
+
+/*
+ * Property definition
+ */
 typedef struct property {
-  const char *id;
-  const char *name;
-  prop_type_t type;
-  size_t off;
-  int options;
-
-  const char *(*str_get)(void *ptr);
-  void (*str_set)(void *ptr, const char *str);
-  const char **(*str_enum)(void *ptr);
-  htsmsg_t *(*str_enum2)(void *ptr);
-
-  void (*notify)(void *ptr);
+  const char  *id;        ///< Property Key
+  const char *name;       ///< Textual description
+  prop_type_t type;       ///< Type
+  size_t      off;        ///< Offset into object
+  int         opts;       ///< Options
+
+  /* String based processing */
+  const char *(*str_get)  (void *ptr);
+  int         (*str_set)  (void *ptr, const char *str);
+  htsmsg_t   *(*str_enum) (void *ptr);
+  // Note: htsmsg_t can either be a string list or object list
+  //       where the object has "key" and "val" fields
+
+  /* Notification callback */
+  void        (*notify)   (void *ptr);
 
 } property_t;
 
 const property_t *prop_find(const property_t *p, const char *name);
 
-void prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg);
-
-void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m);
-
-void prop_read_values(void *obj, const property_t *p, htsmsg_t *m);
-
-int prop_set(void *obj, const property_t *p, const char *key, const char *val);
-
-int prop_update_all(void *obj, const property_t *p,
-                     const char *(*getvalue)(void *opaque, const char *key),
-                     void *opaque);
-
-#define PROPDEF0(_i, _n, _t, _o)\
-  .id      = _i,\
-  .name    = _n,\
-  .type    = _t,\
-  .options = _o
+int prop_write_values
+  (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
 
-#define PROPDEF1(_i, _n, _t, _o, _v)\
-  .id      = _i,\
-  .name    = _n,\
-  .type    = _t,\
-  .off     = offsetof(_o, _v)
+void prop_read_values
+  (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
 
-#define PROPDEF2(_i, _n, _t, _o, _v, _r)\
-  .id      = _i,\
-  .name    = _n,\
-  .type    = _t,\
-  .off     = offsetof(_o, _v),\
-  .options = _r
+void prop_serialize
+  (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
 
-#define PROPDEF3(_i, _n, _t, _o, _v, _c)\
-  .id      = _i,\
-  .name    = _n,\
-  .type    = _t,\
-  .off     = offsetof(_o, _v),\
-  .options = _c
+#endif /* __TVH_PROP_H__ */
 
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/