162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Based on strlist.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 <stdio.h> 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "rblist.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciint rblist__add_node(struct rblist *rblist, const void *new_entry) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct rb_node **p = &rblist->entries.rb_root.rb_node; 1662306a36Sopenharmony_ci struct rb_node *parent = NULL, *new_node; 1762306a36Sopenharmony_ci bool leftmost = true; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci while (*p != NULL) { 2062306a36Sopenharmony_ci int rc; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci parent = *p; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci rc = rblist->node_cmp(parent, new_entry); 2562306a36Sopenharmony_ci if (rc > 0) 2662306a36Sopenharmony_ci p = &(*p)->rb_left; 2762306a36Sopenharmony_ci else if (rc < 0) { 2862306a36Sopenharmony_ci p = &(*p)->rb_right; 2962306a36Sopenharmony_ci leftmost = false; 3062306a36Sopenharmony_ci } 3162306a36Sopenharmony_ci else 3262306a36Sopenharmony_ci return -EEXIST; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci new_node = rblist->node_new(rblist, new_entry); 3662306a36Sopenharmony_ci if (new_node == NULL) 3762306a36Sopenharmony_ci return -ENOMEM; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci rb_link_node(new_node, parent, p); 4062306a36Sopenharmony_ci rb_insert_color_cached(new_node, &rblist->entries, leftmost); 4162306a36Sopenharmony_ci ++rblist->nr_entries; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return 0; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_civoid rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci rb_erase_cached(rb_node, &rblist->entries); 4962306a36Sopenharmony_ci --rblist->nr_entries; 5062306a36Sopenharmony_ci rblist->node_delete(rblist, rb_node); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic struct rb_node *__rblist__findnew(struct rblist *rblist, 5462306a36Sopenharmony_ci const void *entry, 5562306a36Sopenharmony_ci bool create) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct rb_node **p = &rblist->entries.rb_root.rb_node; 5862306a36Sopenharmony_ci struct rb_node *parent = NULL, *new_node = NULL; 5962306a36Sopenharmony_ci bool leftmost = true; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci while (*p != NULL) { 6262306a36Sopenharmony_ci int rc; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci parent = *p; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci rc = rblist->node_cmp(parent, entry); 6762306a36Sopenharmony_ci if (rc > 0) 6862306a36Sopenharmony_ci p = &(*p)->rb_left; 6962306a36Sopenharmony_ci else if (rc < 0) { 7062306a36Sopenharmony_ci p = &(*p)->rb_right; 7162306a36Sopenharmony_ci leftmost = false; 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci else 7462306a36Sopenharmony_ci return parent; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci if (create) { 7862306a36Sopenharmony_ci new_node = rblist->node_new(rblist, entry); 7962306a36Sopenharmony_ci if (new_node) { 8062306a36Sopenharmony_ci rb_link_node(new_node, parent, p); 8162306a36Sopenharmony_ci rb_insert_color_cached(new_node, 8262306a36Sopenharmony_ci &rblist->entries, leftmost); 8362306a36Sopenharmony_ci ++rblist->nr_entries; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci return new_node; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistruct rb_node *rblist__find(struct rblist *rblist, const void *entry) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci return __rblist__findnew(rblist, entry, false); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistruct rb_node *rblist__findnew(struct rblist *rblist, const void *entry) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci return __rblist__findnew(rblist, entry, true); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_civoid rblist__init(struct rblist *rblist) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci if (rblist != NULL) { 10362306a36Sopenharmony_ci rblist->entries = RB_ROOT_CACHED; 10462306a36Sopenharmony_ci rblist->nr_entries = 0; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_civoid rblist__exit(struct rblist *rblist) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct rb_node *pos, *next = rb_first_cached(&rblist->entries); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci while (next) { 11562306a36Sopenharmony_ci pos = next; 11662306a36Sopenharmony_ci next = rb_next(pos); 11762306a36Sopenharmony_ci rblist__remove_node(rblist, pos); 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_civoid rblist__delete(struct rblist *rblist) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci if (rblist != NULL) { 12462306a36Sopenharmony_ci rblist__exit(rblist); 12562306a36Sopenharmony_ci free(rblist); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistruct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci struct rb_node *node; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci for (node = rb_first_cached(&rblist->entries); node; 13462306a36Sopenharmony_ci node = rb_next(node)) { 13562306a36Sopenharmony_ci if (!idx--) 13662306a36Sopenharmony_ci return node; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return NULL; 14062306a36Sopenharmony_ci} 141