linux/tools/perf/util/strlist.c
<<
>>
Prefs
   1/*
   2 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
   3 *
   4 * Licensed under the GPLv2.
   5 */
   6
   7#include "strlist.h"
   8#include <errno.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12
  13static struct str_node *str_node__new(const char *s, bool dupstr)
  14{
  15        struct str_node *self = malloc(sizeof(*self));
  16
  17        if (self != NULL) {
  18                if (dupstr) {
  19                        s = strdup(s);
  20                        if (s == NULL)
  21                                goto out_delete;
  22                }
  23                self->s = s;
  24        }
  25
  26        return self;
  27
  28out_delete:
  29        free(self);
  30        return NULL;
  31}
  32
  33static void str_node__delete(struct str_node *self, bool dupstr)
  34{
  35        if (dupstr)
  36                free((void *)self->s);
  37        free(self);
  38}
  39
  40int strlist__add(struct strlist *self, const char *new_entry)
  41{
  42        struct rb_node **p = &self->entries.rb_node;
  43        struct rb_node *parent = NULL;
  44        struct str_node *sn;
  45
  46        while (*p != NULL) {
  47                int rc;
  48
  49                parent = *p;
  50                sn = rb_entry(parent, struct str_node, rb_node);
  51                rc = strcmp(sn->s, new_entry);
  52
  53                if (rc > 0)
  54                        p = &(*p)->rb_left;
  55                else if (rc < 0)
  56                        p = &(*p)->rb_right;
  57                else
  58                        return -EEXIST;
  59        }
  60
  61        sn = str_node__new(new_entry, self->dupstr);
  62        if (sn == NULL)
  63                return -ENOMEM;
  64
  65        rb_link_node(&sn->rb_node, parent, p);
  66        rb_insert_color(&sn->rb_node, &self->entries);
  67        ++self->nr_entries;
  68
  69        return 0;
  70}
  71
  72int strlist__load(struct strlist *self, const char *filename)
  73{
  74        char entry[1024];
  75        int err;
  76        FILE *fp = fopen(filename, "r");
  77
  78        if (fp == NULL)
  79                return errno;
  80
  81        while (fgets(entry, sizeof(entry), fp) != NULL) {
  82                const size_t len = strlen(entry);
  83
  84                if (len == 0)
  85                        continue;
  86                entry[len - 1] = '\0';
  87
  88                err = strlist__add(self, entry);
  89                if (err != 0)
  90                        goto out;
  91        }
  92
  93        err = 0;
  94out:
  95        fclose(fp);
  96        return err;
  97}
  98
  99void strlist__remove(struct strlist *self, struct str_node *sn)
 100{
 101        rb_erase(&sn->rb_node, &self->entries);
 102        str_node__delete(sn, self->dupstr);
 103}
 104
 105bool strlist__has_entry(struct strlist *self, const char *entry)
 106{
 107        struct rb_node **p = &self->entries.rb_node;
 108        struct rb_node *parent = NULL;
 109
 110        while (*p != NULL) {
 111                struct str_node *sn;
 112                int rc;
 113
 114                parent = *p;
 115                sn = rb_entry(parent, struct str_node, rb_node);
 116                rc = strcmp(sn->s, entry);
 117
 118                if (rc > 0)
 119                        p = &(*p)->rb_left;
 120                else if (rc < 0)
 121                        p = &(*p)->rb_right;
 122                else
 123                        return true;
 124        }
 125
 126        return false;
 127}
 128
 129static int strlist__parse_list_entry(struct strlist *self, const char *s)
 130{
 131        if (strncmp(s, "file://", 7) == 0)
 132                return strlist__load(self, s + 7);
 133
 134        return strlist__add(self, s);
 135}
 136
 137int strlist__parse_list(struct strlist *self, const char *s)
 138{
 139        char *sep;
 140        int err;
 141
 142        while ((sep = strchr(s, ',')) != NULL) {
 143                *sep = '\0';
 144                err = strlist__parse_list_entry(self, s);
 145                *sep = ',';
 146                if (err != 0)
 147                        return err;
 148                s = sep + 1;
 149        }
 150
 151        return *s ? strlist__parse_list_entry(self, s) : 0;
 152}
 153
 154struct strlist *strlist__new(bool dupstr, const char *slist)
 155{
 156        struct strlist *self = malloc(sizeof(*self));
 157
 158        if (self != NULL) {
 159                self->entries    = RB_ROOT;
 160                self->dupstr     = dupstr;
 161                self->nr_entries = 0;
 162                if (slist && strlist__parse_list(self, slist) != 0)
 163                        goto out_error;
 164        }
 165
 166        return self;
 167out_error:
 168        free(self);
 169        return NULL;
 170}
 171
 172void strlist__delete(struct strlist *self)
 173{
 174        if (self != NULL) {
 175                struct str_node *pos;
 176                struct rb_node *next = rb_first(&self->entries);
 177
 178                while (next) {
 179                        pos = rb_entry(next, struct str_node, rb_node);
 180                        next = rb_next(&pos->rb_node);
 181                        strlist__remove(self, pos);
 182                }
 183                self->entries = RB_ROOT;
 184                free(self);
 185        }
 186}
 187
 188struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
 189{
 190        struct rb_node *nd;
 191
 192        for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
 193                struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
 194
 195                if (!idx--)
 196                        return pos;
 197        }
 198
 199        return NULL;
 200}
 201