|  | /* | 
|  | * Based on intlist.c by: | 
|  | * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> | 
|  | * | 
|  | * Licensed under the GPLv2. | 
|  | */ | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <stdlib.h> | 
|  | #include <linux/compiler.h> | 
|  |  | 
|  | #include "intlist.h" | 
|  |  | 
|  | static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, | 
|  | const void *entry) | 
|  | { | 
|  | int i = (int)((long)entry); | 
|  | struct rb_node *rc = NULL; | 
|  | struct int_node *node = malloc(sizeof(*node)); | 
|  |  | 
|  | if (node != NULL) { | 
|  | node->i = i; | 
|  | node->priv = NULL; | 
|  | rc = &node->rb_node; | 
|  | } | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | static void int_node__delete(struct int_node *ilist) | 
|  | { | 
|  | free(ilist); | 
|  | } | 
|  |  | 
|  | static void intlist__node_delete(struct rblist *rblist __maybe_unused, | 
|  | struct rb_node *rb_node) | 
|  | { | 
|  | struct int_node *node = container_of(rb_node, struct int_node, rb_node); | 
|  |  | 
|  | int_node__delete(node); | 
|  | } | 
|  |  | 
|  | static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) | 
|  | { | 
|  | int i = (int)((long)entry); | 
|  | struct int_node *node = container_of(rb_node, struct int_node, rb_node); | 
|  |  | 
|  | return node->i - i; | 
|  | } | 
|  |  | 
|  | int intlist__add(struct intlist *ilist, int i) | 
|  | { | 
|  | return rblist__add_node(&ilist->rblist, (void *)((long)i)); | 
|  | } | 
|  |  | 
|  | void intlist__remove(struct intlist *ilist, struct int_node *node) | 
|  | { | 
|  | rblist__remove_node(&ilist->rblist, &node->rb_node); | 
|  | } | 
|  |  | 
|  | static struct int_node *__intlist__findnew(struct intlist *ilist, | 
|  | int i, bool create) | 
|  | { | 
|  | struct int_node *node = NULL; | 
|  | struct rb_node *rb_node; | 
|  |  | 
|  | if (ilist == NULL) | 
|  | return NULL; | 
|  |  | 
|  | if (create) | 
|  | rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); | 
|  | else | 
|  | rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); | 
|  |  | 
|  | if (rb_node) | 
|  | node = container_of(rb_node, struct int_node, rb_node); | 
|  |  | 
|  | return node; | 
|  | } | 
|  |  | 
|  | struct int_node *intlist__find(struct intlist *ilist, int i) | 
|  | { | 
|  | return __intlist__findnew(ilist, i, false); | 
|  | } | 
|  |  | 
|  | struct int_node *intlist__findnew(struct intlist *ilist, int i) | 
|  | { | 
|  | return __intlist__findnew(ilist, i, true); | 
|  | } | 
|  |  | 
|  | static int intlist__parse_list(struct intlist *ilist, const char *s) | 
|  | { | 
|  | char *sep; | 
|  | int err; | 
|  |  | 
|  | do { | 
|  | long value = strtol(s, &sep, 10); | 
|  | err = -EINVAL; | 
|  | if (*sep != ',' && *sep != '\0') | 
|  | break; | 
|  | err = intlist__add(ilist, value); | 
|  | if (err) | 
|  | break; | 
|  | s = sep + 1; | 
|  | } while (*sep != '\0'); | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  | struct intlist *intlist__new(const char *slist) | 
|  | { | 
|  | struct intlist *ilist = malloc(sizeof(*ilist)); | 
|  |  | 
|  | if (ilist != NULL) { | 
|  | rblist__init(&ilist->rblist); | 
|  | ilist->rblist.node_cmp    = intlist__node_cmp; | 
|  | ilist->rblist.node_new    = intlist__node_new; | 
|  | ilist->rblist.node_delete = intlist__node_delete; | 
|  |  | 
|  | if (slist && intlist__parse_list(ilist, slist)) | 
|  | goto out_delete; | 
|  | } | 
|  |  | 
|  | return ilist; | 
|  | out_delete: | 
|  | intlist__delete(ilist); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | void intlist__delete(struct intlist *ilist) | 
|  | { | 
|  | if (ilist != NULL) | 
|  | rblist__delete(&ilist->rblist); | 
|  | } | 
|  |  | 
|  | struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) | 
|  | { | 
|  | struct int_node *node = NULL; | 
|  | struct rb_node *rb_node; | 
|  |  | 
|  | rb_node = rblist__entry(&ilist->rblist, idx); | 
|  | if (rb_node) | 
|  | node = container_of(rb_node, struct int_node, rb_node); | 
|  |  | 
|  | return node; | 
|  | } |