linux/tools/perf/util/intlist.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Based on intlist.c by:
   4 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
   5 */
   6
   7#include <errno.h>
   8#include <stdlib.h>
   9#include <linux/compiler.h>
  10
  11#include "intlist.h"
  12
  13static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
  14                                         const void *entry)
  15{
  16        unsigned long i = (unsigned long)entry;
  17        struct rb_node *rc = NULL;
  18        struct int_node *node = malloc(sizeof(*node));
  19
  20        if (node != NULL) {
  21                node->i = i;
  22                node->priv = NULL;
  23                rc = &node->rb_node;
  24        }
  25
  26        return rc;
  27}
  28
  29static void int_node__delete(struct int_node *ilist)
  30{
  31        free(ilist);
  32}
  33
  34static void intlist__node_delete(struct rblist *rblist __maybe_unused,
  35                                 struct rb_node *rb_node)
  36{
  37        struct int_node *node = container_of(rb_node, struct int_node, rb_node);
  38
  39        int_node__delete(node);
  40}
  41
  42static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
  43{
  44        unsigned long i = (unsigned long)entry;
  45        struct int_node *node = container_of(rb_node, struct int_node, rb_node);
  46
  47        if (node->i > i)
  48                return 1;
  49        else if (node->i < i)
  50                return -1;
  51
  52        return 0;
  53}
  54
  55int intlist__add(struct intlist *ilist, unsigned long i)
  56{
  57        return rblist__add_node(&ilist->rblist, (void *)i);
  58}
  59
  60void intlist__remove(struct intlist *ilist, struct int_node *node)
  61{
  62        rblist__remove_node(&ilist->rblist, &node->rb_node);
  63}
  64
  65static struct int_node *__intlist__findnew(struct intlist *ilist,
  66                                           unsigned long i, bool create)
  67{
  68        struct int_node *node = NULL;
  69        struct rb_node *rb_node;
  70
  71        if (ilist == NULL)
  72                return NULL;
  73
  74        if (create)
  75                rb_node = rblist__findnew(&ilist->rblist, (void *)i);
  76        else
  77                rb_node = rblist__find(&ilist->rblist, (void *)i);
  78
  79        if (rb_node)
  80                node = container_of(rb_node, struct int_node, rb_node);
  81
  82        return node;
  83}
  84
  85struct int_node *intlist__find(struct intlist *ilist, unsigned long i)
  86{
  87        return __intlist__findnew(ilist, i, false);
  88}
  89
  90struct int_node *intlist__findnew(struct intlist *ilist, unsigned long i)
  91{
  92        return __intlist__findnew(ilist, i, true);
  93}
  94
  95static int intlist__parse_list(struct intlist *ilist, const char *s)
  96{
  97        char *sep;
  98        int err;
  99
 100        do {
 101                unsigned long value = strtol(s, &sep, 10);
 102                err = -EINVAL;
 103                if (*sep != ',' && *sep != '\0')
 104                        break;
 105                err = intlist__add(ilist, value);
 106                if (err)
 107                        break;
 108                s = sep + 1;
 109        } while (*sep != '\0');
 110
 111        return err;
 112}
 113
 114struct intlist *intlist__new(const char *slist)
 115{
 116        struct intlist *ilist = malloc(sizeof(*ilist));
 117
 118        if (ilist != NULL) {
 119                rblist__init(&ilist->rblist);
 120                ilist->rblist.node_cmp    = intlist__node_cmp;
 121                ilist->rblist.node_new    = intlist__node_new;
 122                ilist->rblist.node_delete = intlist__node_delete;
 123
 124                if (slist && intlist__parse_list(ilist, slist))
 125                        goto out_delete;
 126        }
 127
 128        return ilist;
 129out_delete:
 130        intlist__delete(ilist);
 131        return NULL;
 132}
 133
 134void intlist__delete(struct intlist *ilist)
 135{
 136        if (ilist != NULL)
 137                rblist__delete(&ilist->rblist);
 138}
 139
 140struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
 141{
 142        struct int_node *node = NULL;
 143        struct rb_node *rb_node;
 144
 145        rb_node = rblist__entry(&ilist->rblist, idx);
 146        if (rb_node)
 147                node = container_of(rb_node, struct int_node, rb_node);
 148
 149        return node;
 150}
 151