18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Based on strlist.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 <stdio.h> 98c2ecf20Sopenharmony_ci#include <stdlib.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "rblist.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciint rblist__add_node(struct rblist *rblist, const void *new_entry) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci struct rb_node **p = &rblist->entries.rb_root.rb_node; 168c2ecf20Sopenharmony_ci struct rb_node *parent = NULL, *new_node; 178c2ecf20Sopenharmony_ci bool leftmost = true; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci while (*p != NULL) { 208c2ecf20Sopenharmony_ci int rc; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci parent = *p; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci rc = rblist->node_cmp(parent, new_entry); 258c2ecf20Sopenharmony_ci if (rc > 0) 268c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 278c2ecf20Sopenharmony_ci else if (rc < 0) { 288c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 298c2ecf20Sopenharmony_ci leftmost = false; 308c2ecf20Sopenharmony_ci } 318c2ecf20Sopenharmony_ci else 328c2ecf20Sopenharmony_ci return -EEXIST; 338c2ecf20Sopenharmony_ci } 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci new_node = rblist->node_new(rblist, new_entry); 368c2ecf20Sopenharmony_ci if (new_node == NULL) 378c2ecf20Sopenharmony_ci return -ENOMEM; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci rb_link_node(new_node, parent, p); 408c2ecf20Sopenharmony_ci rb_insert_color_cached(new_node, &rblist->entries, leftmost); 418c2ecf20Sopenharmony_ci ++rblist->nr_entries; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_civoid rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci rb_erase_cached(rb_node, &rblist->entries); 498c2ecf20Sopenharmony_ci --rblist->nr_entries; 508c2ecf20Sopenharmony_ci rblist->node_delete(rblist, rb_node); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic struct rb_node *__rblist__findnew(struct rblist *rblist, 548c2ecf20Sopenharmony_ci const void *entry, 558c2ecf20Sopenharmony_ci bool create) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci struct rb_node **p = &rblist->entries.rb_root.rb_node; 588c2ecf20Sopenharmony_ci struct rb_node *parent = NULL, *new_node = NULL; 598c2ecf20Sopenharmony_ci bool leftmost = true; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci while (*p != NULL) { 628c2ecf20Sopenharmony_ci int rc; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci parent = *p; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci rc = rblist->node_cmp(parent, entry); 678c2ecf20Sopenharmony_ci if (rc > 0) 688c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 698c2ecf20Sopenharmony_ci else if (rc < 0) { 708c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 718c2ecf20Sopenharmony_ci leftmost = false; 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci return parent; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (create) { 788c2ecf20Sopenharmony_ci new_node = rblist->node_new(rblist, entry); 798c2ecf20Sopenharmony_ci if (new_node) { 808c2ecf20Sopenharmony_ci rb_link_node(new_node, parent, p); 818c2ecf20Sopenharmony_ci rb_insert_color_cached(new_node, 828c2ecf20Sopenharmony_ci &rblist->entries, leftmost); 838c2ecf20Sopenharmony_ci ++rblist->nr_entries; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return new_node; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistruct rb_node *rblist__find(struct rblist *rblist, const void *entry) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci return __rblist__findnew(rblist, entry, false); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistruct rb_node *rblist__findnew(struct rblist *rblist, const void *entry) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci return __rblist__findnew(rblist, entry, true); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_civoid rblist__init(struct rblist *rblist) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci if (rblist != NULL) { 1038c2ecf20Sopenharmony_ci rblist->entries = RB_ROOT_CACHED; 1048c2ecf20Sopenharmony_ci rblist->nr_entries = 0; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_civoid rblist__exit(struct rblist *rblist) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct rb_node *pos, *next = rb_first_cached(&rblist->entries); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci while (next) { 1158c2ecf20Sopenharmony_ci pos = next; 1168c2ecf20Sopenharmony_ci next = rb_next(pos); 1178c2ecf20Sopenharmony_ci rblist__remove_node(rblist, pos); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_civoid rblist__delete(struct rblist *rblist) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci if (rblist != NULL) { 1248c2ecf20Sopenharmony_ci rblist__exit(rblist); 1258c2ecf20Sopenharmony_ci free(rblist); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistruct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct rb_node *node; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci for (node = rb_first_cached(&rblist->entries); node; 1348c2ecf20Sopenharmony_ci node = rb_next(node)) { 1358c2ecf20Sopenharmony_ci if (!idx--) 1368c2ecf20Sopenharmony_ci return node; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return NULL; 1408c2ecf20Sopenharmony_ci} 141