Merge pull request #1575 from rubenk/dragonflybsd-utils-mount
[collectd.git] / src / utils_llist.c
index d8694e3..4c5645b 100644 (file)
  * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  * See the GNU General Public Licence for more details.
  *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
  *   Florian Forster <octo at verplant.org>
@@ -35,6 +34,7 @@ struct llist_s
 {
        llentry_t *head;
        llentry_t *tail;
+       int size;
 };
 
 /*
@@ -58,6 +58,9 @@ void llist_destroy (llist_t *l)
        llentry_t *e_this;
        llentry_t *e_next;
 
+       if (l == NULL)
+               return;
+
        for (e_this = l->head; e_this != NULL; e_this = e_next)
        {
                e_next = e_this->next;
@@ -67,22 +70,16 @@ void llist_destroy (llist_t *l)
        free (l);
 }
 
-llentry_t *llentry_create (const char *key, void *value)
+llentry_t *llentry_create (char *key, void *value)
 {
        llentry_t *e;
 
        e = (llentry_t *) malloc (sizeof (llentry_t));
-       if (e == NULL)
-               return (NULL);
-
-       e->key   = strdup (key);
-       e->value = value;
-       e->next  = NULL;
-
-       if (e->key == NULL)
+       if (e)
        {
-               free (e);
-               return (NULL);
+               e->key   = key;
+               e->value = value;
+               e->next  = NULL;
        }
 
        return (e);
@@ -90,7 +87,6 @@ llentry_t *llentry_create (const char *key, void *value)
 
 void llentry_destroy (llentry_t *e)
 {
-       free (e->key);
        free (e);
 }
 
@@ -104,18 +100,28 @@ void llist_append (llist_t *l, llentry_t *e)
                l->tail->next = e;
 
        l->tail = e;
+
+       ++(l->size);
 }
 
 void llist_prepend (llist_t *l, llentry_t *e)
 {
        e->next = l->head;
        l->head = e;
+
+       if (l->tail == NULL)
+               l->tail = e;
+
+       ++(l->size);
 }
 
 void llist_remove (llist_t *l, llentry_t *e)
 {
        llentry_t *prev;
 
+       if ((l == NULL) || (e == NULL))
+               return;
+
        prev = l->head;
        while ((prev != NULL) && (prev->next != e))
                prev = prev->next;
@@ -126,25 +132,58 @@ void llist_remove (llist_t *l, llentry_t *e)
                l->head = e->next;
        if (l->tail == e)
                l->tail = prev;
+
+       --(l->size);
+}
+
+int llist_size (llist_t *l)
+{
+       return (l ? l->size : 0);
+}
+
+static int llist_strcmp (llentry_t *e, void *ud)
+{
+       if ((e == NULL) || (ud == NULL))
+               return (-1);
+       return (strcmp (e->key, (const char *)ud));
 }
 
 llentry_t *llist_search (llist_t *l, const char *key)
 {
+       return (llist_search_custom (l, llist_strcmp, (void *)key));
+}
+
+llentry_t *llist_search_custom (llist_t *l,
+               int (*compare) (llentry_t *, void *), void *user_data)
+{
        llentry_t *e;
 
-       for (e = l->head; e != NULL; e = e->next)
-               if (strcmp (key, e->key) == 0)
+       if (l == NULL)
+               return (NULL);
+
+       e = l->head;
+       while (e != NULL) {
+               llentry_t *next = e->next;
+
+               if (compare (e, user_data) == 0)
                        break;
 
+               e = next;
+       }
+
        return (e);
 }
 
 llentry_t *llist_head (llist_t *l)
 {
+       if (l == NULL)
+               return (NULL);
        return (l->head);
 }
 
 llentry_t *llist_tail (llist_t *l)
 {
+       if (l == NULL)
+               return (NULL);
        return (l->tail);
 }