18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Based on intlist.c by: 48c2ecf20Sopenharmony_ci * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <errno.h> 88c2ecf20Sopenharmony_ci#include <stdlib.h> 98c2ecf20Sopenharmony_ci#include <linux/compiler.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "intlist.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, 148c2ecf20Sopenharmony_ci const void *entry) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci int i = (int)((long)entry); 178c2ecf20Sopenharmony_ci struct rb_node *rc = NULL; 188c2ecf20Sopenharmony_ci struct int_node *node = malloc(sizeof(*node)); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci if (node != NULL) { 218c2ecf20Sopenharmony_ci node->i = i; 228c2ecf20Sopenharmony_ci node->priv = NULL; 238c2ecf20Sopenharmony_ci rc = &node->rb_node; 248c2ecf20Sopenharmony_ci } 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci return rc; 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic void int_node__delete(struct int_node *ilist) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci free(ilist); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic void intlist__node_delete(struct rblist *rblist __maybe_unused, 358c2ecf20Sopenharmony_ci struct rb_node *rb_node) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci struct int_node *node = container_of(rb_node, struct int_node, rb_node); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci int_node__delete(node); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int intlist__node_cmp(struct rb_node *rb_node, const void *entry) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci int i = (int)((long)entry); 458c2ecf20Sopenharmony_ci struct int_node *node = container_of(rb_node, struct int_node, rb_node); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci return node->i - i; 488c2ecf20Sopenharmony_ci} 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciint intlist__add(struct intlist *ilist, int i) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci return rblist__add_node(&ilist->rblist, (void *)((long)i)); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_civoid intlist__remove(struct intlist *ilist, struct int_node *node) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci rblist__remove_node(&ilist->rblist, &node->rb_node); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic struct int_node *__intlist__findnew(struct intlist *ilist, 618c2ecf20Sopenharmony_ci int i, bool create) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct int_node *node = NULL; 648c2ecf20Sopenharmony_ci struct rb_node *rb_node; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (ilist == NULL) 678c2ecf20Sopenharmony_ci return NULL; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (create) 708c2ecf20Sopenharmony_ci rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (rb_node) 758c2ecf20Sopenharmony_ci node = container_of(rb_node, struct int_node, rb_node); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return node; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct int_node *intlist__find(struct intlist *ilist, int i) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci return __intlist__findnew(ilist, i, false); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct int_node *intlist__findnew(struct intlist *ilist, int i) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci return __intlist__findnew(ilist, i, true); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int intlist__parse_list(struct intlist *ilist, const char *s) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci char *sep; 938c2ecf20Sopenharmony_ci int err; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci do { 968c2ecf20Sopenharmony_ci long value = strtol(s, &sep, 10); 978c2ecf20Sopenharmony_ci err = -EINVAL; 988c2ecf20Sopenharmony_ci if (*sep != ',' && *sep != '\0') 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci err = intlist__add(ilist, value); 1018c2ecf20Sopenharmony_ci if (err) 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci s = sep + 1; 1048c2ecf20Sopenharmony_ci } while (*sep != '\0'); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return err; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistruct intlist *intlist__new(const char *slist) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci struct intlist *ilist = malloc(sizeof(*ilist)); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (ilist != NULL) { 1148c2ecf20Sopenharmony_ci rblist__init(&ilist->rblist); 1158c2ecf20Sopenharmony_ci ilist->rblist.node_cmp = intlist__node_cmp; 1168c2ecf20Sopenharmony_ci ilist->rblist.node_new = intlist__node_new; 1178c2ecf20Sopenharmony_ci ilist->rblist.node_delete = intlist__node_delete; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (slist && intlist__parse_list(ilist, slist)) 1208c2ecf20Sopenharmony_ci goto out_delete; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci return ilist; 1248c2ecf20Sopenharmony_ciout_delete: 1258c2ecf20Sopenharmony_ci intlist__delete(ilist); 1268c2ecf20Sopenharmony_ci return NULL; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_civoid intlist__delete(struct intlist *ilist) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci if (ilist != NULL) 1328c2ecf20Sopenharmony_ci rblist__delete(&ilist->rblist); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistruct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci struct int_node *node = NULL; 1388c2ecf20Sopenharmony_ci struct rb_node *rb_node; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci rb_node = rblist__entry(&ilist->rblist, idx); 1418c2ecf20Sopenharmony_ci if (rb_node) 1428c2ecf20Sopenharmony_ci node = container_of(rb_node, struct int_node, rb_node); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci return node; 1458c2ecf20Sopenharmony_ci} 146