162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Based on intlist.c by: 462306a36Sopenharmony_ci * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <errno.h> 862306a36Sopenharmony_ci#include <stdlib.h> 962306a36Sopenharmony_ci#include <linux/compiler.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "intlist.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, 1462306a36Sopenharmony_ci const void *entry) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci unsigned long i = (unsigned long)entry; 1762306a36Sopenharmony_ci struct rb_node *rc = NULL; 1862306a36Sopenharmony_ci struct int_node *node = malloc(sizeof(*node)); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if (node != NULL) { 2162306a36Sopenharmony_ci node->i = i; 2262306a36Sopenharmony_ci node->priv = NULL; 2362306a36Sopenharmony_ci rc = &node->rb_node; 2462306a36Sopenharmony_ci } 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci return rc; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic void int_node__delete(struct int_node *ilist) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci free(ilist); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void intlist__node_delete(struct rblist *rblist __maybe_unused, 3562306a36Sopenharmony_ci struct rb_node *rb_node) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct int_node *node = container_of(rb_node, struct int_node, rb_node); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci int_node__delete(node); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic int intlist__node_cmp(struct rb_node *rb_node, const void *entry) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci unsigned long i = (unsigned long)entry; 4562306a36Sopenharmony_ci struct int_node *node = container_of(rb_node, struct int_node, rb_node); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (node->i > i) 4862306a36Sopenharmony_ci return 1; 4962306a36Sopenharmony_ci else if (node->i < i) 5062306a36Sopenharmony_ci return -1; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci return 0; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciint intlist__add(struct intlist *ilist, unsigned long i) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci return rblist__add_node(&ilist->rblist, (void *)i); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_civoid intlist__remove(struct intlist *ilist, struct int_node *node) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci rblist__remove_node(&ilist->rblist, &node->rb_node); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic struct int_node *__intlist__findnew(struct intlist *ilist, 6662306a36Sopenharmony_ci unsigned long i, bool create) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci struct int_node *node = NULL; 6962306a36Sopenharmony_ci struct rb_node *rb_node; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (ilist == NULL) 7262306a36Sopenharmony_ci return NULL; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (create) 7562306a36Sopenharmony_ci rb_node = rblist__findnew(&ilist->rblist, (void *)i); 7662306a36Sopenharmony_ci else 7762306a36Sopenharmony_ci rb_node = rblist__find(&ilist->rblist, (void *)i); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (rb_node) 8062306a36Sopenharmony_ci node = container_of(rb_node, struct int_node, rb_node); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return node; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct int_node *intlist__find(struct intlist *ilist, unsigned long i) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci return __intlist__findnew(ilist, i, false); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistruct int_node *intlist__findnew(struct intlist *ilist, unsigned long i) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci return __intlist__findnew(ilist, i, true); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int intlist__parse_list(struct intlist *ilist, const char *s) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci char *sep; 9862306a36Sopenharmony_ci int err; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci do { 10162306a36Sopenharmony_ci unsigned long value = strtol(s, &sep, 10); 10262306a36Sopenharmony_ci err = -EINVAL; 10362306a36Sopenharmony_ci if (*sep != ',' && *sep != '\0') 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci err = intlist__add(ilist, value); 10662306a36Sopenharmony_ci if (err) 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci s = sep + 1; 10962306a36Sopenharmony_ci } while (*sep != '\0'); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return err; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistruct intlist *intlist__new(const char *slist) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci struct intlist *ilist = malloc(sizeof(*ilist)); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (ilist != NULL) { 11962306a36Sopenharmony_ci rblist__init(&ilist->rblist); 12062306a36Sopenharmony_ci ilist->rblist.node_cmp = intlist__node_cmp; 12162306a36Sopenharmony_ci ilist->rblist.node_new = intlist__node_new; 12262306a36Sopenharmony_ci ilist->rblist.node_delete = intlist__node_delete; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (slist && intlist__parse_list(ilist, slist)) 12562306a36Sopenharmony_ci goto out_delete; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return ilist; 12962306a36Sopenharmony_ciout_delete: 13062306a36Sopenharmony_ci intlist__delete(ilist); 13162306a36Sopenharmony_ci return NULL; 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_civoid intlist__delete(struct intlist *ilist) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci if (ilist != NULL) 13762306a36Sopenharmony_ci rblist__delete(&ilist->rblist); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistruct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct int_node *node = NULL; 14362306a36Sopenharmony_ci struct rb_node *rb_node; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci rb_node = rblist__entry(&ilist->rblist, idx); 14662306a36Sopenharmony_ci if (rb_node) 14762306a36Sopenharmony_ci node = container_of(rb_node, struct int_node, rb_node); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return node; 15062306a36Sopenharmony_ci} 151