Home | History | Annotate | Download | only in util
      1 /*
      2  * Based on intlist.c by:
      3  * (c) 2009 Arnaldo Carvalho de Melo <acme (at) redhat.com>
      4  *
      5  * Licensed under the GPLv2.
      6  */
      7 
      8 #include <errno.h>
      9 #include <stdlib.h>
     10 #include <linux/compiler.h>
     11 
     12 #include "intlist.h"
     13 
     14 static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
     15 					 const void *entry)
     16 {
     17 	int i = (int)((long)entry);
     18 	struct rb_node *rc = NULL;
     19 	struct int_node *node = malloc(sizeof(*node));
     20 
     21 	if (node != NULL) {
     22 		node->i = i;
     23 		rc = &node->rb_node;
     24 	}
     25 
     26 	return rc;
     27 }
     28 
     29 static void int_node__delete(struct int_node *ilist)
     30 {
     31 	free(ilist);
     32 }
     33 
     34 static void intlist__node_delete(struct rblist *rblist __maybe_unused,
     35 				 struct rb_node *rb_node)
     36 {
     37 	struct int_node *node = container_of(rb_node, struct int_node, rb_node);
     38 
     39 	int_node__delete(node);
     40 }
     41 
     42 static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
     43 {
     44 	int i = (int)((long)entry);
     45 	struct int_node *node = container_of(rb_node, struct int_node, rb_node);
     46 
     47 	return node->i - i;
     48 }
     49 
     50 int intlist__add(struct intlist *ilist, int i)
     51 {
     52 	return rblist__add_node(&ilist->rblist, (void *)((long)i));
     53 }
     54 
     55 void intlist__remove(struct intlist *ilist, struct int_node *node)
     56 {
     57 	rblist__remove_node(&ilist->rblist, &node->rb_node);
     58 }
     59 
     60 struct int_node *intlist__find(struct intlist *ilist, int i)
     61 {
     62 	struct int_node *node;
     63 	struct rb_node *rb_node;
     64 
     65 	if (ilist == NULL)
     66 		return NULL;
     67 
     68 	node = NULL;
     69 	rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
     70 	if (rb_node)
     71 		node = container_of(rb_node, struct int_node, rb_node);
     72 
     73 	return node;
     74 }
     75 
     76 static int intlist__parse_list(struct intlist *ilist, const char *s)
     77 {
     78 	char *sep;
     79 	int err;
     80 
     81 	do {
     82 		long value = strtol(s, &sep, 10);
     83 		err = -EINVAL;
     84 		if (*sep != ',' && *sep != '\0')
     85 			break;
     86 		err = intlist__add(ilist, value);
     87 		if (err)
     88 			break;
     89 		s = sep + 1;
     90 	} while (*sep != '\0');
     91 
     92 	return err;
     93 }
     94 
     95 struct intlist *intlist__new(const char *slist)
     96 {
     97 	struct intlist *ilist = malloc(sizeof(*ilist));
     98 
     99 	if (ilist != NULL) {
    100 		rblist__init(&ilist->rblist);
    101 		ilist->rblist.node_cmp    = intlist__node_cmp;
    102 		ilist->rblist.node_new    = intlist__node_new;
    103 		ilist->rblist.node_delete = intlist__node_delete;
    104 
    105 		if (slist && intlist__parse_list(ilist, slist))
    106 			goto out_delete;
    107 	}
    108 
    109 	return ilist;
    110 out_delete:
    111 	intlist__delete(ilist);
    112 	return NULL;
    113 }
    114 
    115 void intlist__delete(struct intlist *ilist)
    116 {
    117 	if (ilist != NULL)
    118 		rblist__delete(&ilist->rblist);
    119 }
    120 
    121 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
    122 {
    123 	struct int_node *node = NULL;
    124 	struct rb_node *rb_node;
    125 
    126 	rb_node = rblist__entry(&ilist->rblist, idx);
    127 	if (rb_node)
    128 		node = container_of(rb_node, struct int_node, rb_node);
    129 
    130 	return node;
    131 }
    132