// SPDX-License-Identifier: GPL-2.0-only /* * Based on intlist.c by: * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> */ #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) { unsigned long i = (unsigned 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) { unsigned long i = (unsigned long)entry; struct int_node *node = container_of(rb_node, struct int_node, rb_node); if (node->i > i) return 1; else if (node->i < i) return -1; return 0; } int intlist__add(struct intlist *ilist, unsigned long i) { return rblist__add_node(&ilist->rblist, (void *)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, unsigned long 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 *)i); else rb_node = rblist__find(&ilist->rblist, (void *)i); if (rb_node) node = container_of(rb_node, struct int_node, rb_node); return node; } struct int_node *intlist__find(struct intlist *ilist, unsigned long i) { return __intlist__findnew(ilist, i, false); } struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i) { return __intlist__findnew(ilist, i, true); } static int intlist__parse_list(struct intlist *ilist, const char *s) { char *sep; int err; do { unsigned 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; }