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 "util.h"
   9#include <errno.h>
  10#include <stdio.h>
  11#include <stdlib.h>
  12#include <string.h>
  13#include <unistd.h>
  14
  15static
  16struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
  17{
  18        const char *s = entry;
  19        struct rb_node *rc = NULL;
  20        struct strlist *strlist = container_of(rblist, struct strlist, rblist);
  21        struct str_node *snode = malloc(sizeof(*snode));
  22
  23        if (snode != NULL) {
  24                if (strlist->dupstr) {
  25                        s = strdup(s);
  26                        if (s == NULL)
  27                                goto out_delete;
  28                }
  29                snode->s = s;
  30                rc = &snode->rb_node;
  31        }
  32
  33        return rc;
  34
  35out_delete:
  36        free(snode);
  37        return NULL;
  38}
  39
  40static void str_node__delete(struct str_node *snode, bool dupstr)
  41{
  42        if (dupstr)
  43                zfree((char **)&snode->s);
  44        free(snode);
  45}
  46
  47static
  48void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)
  49{
  50        struct strlist *slist = container_of(rblist, struct strlist, rblist);
  51        struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
  52
  53        str_node__delete(snode, slist->dupstr);
  54}
  55
  56static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)
  57{
  58        const char *str = entry;
  59        struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
  60
  61        return strcmp(snode->s, str);
  62}
  63
  64int strlist__add(struct strlist *slist, const char *new_entry)
  65{
  66        return rblist__add_node(&slist->rblist, new_entry);
  67}
  68
  69int strlist__load(struct strlist *slist, const char *filename)
  70{
  71        char entry[1024];
  72        int err;
  73        FILE *fp = fopen(filename, "r");
  74
  75        if (fp == NULL)
  76                return -errno;
  77
  78        while (fgets(entry, sizeof(entry), fp) != NULL) {
  79                const size_t len = strlen(entry);
  80
  81                if (len == 0)
  82                        continue;
  83                entry[len - 1] = '\0';
  84
  85                err = strlist__add(slist, entry);
  86                if (err != 0)
  87                        goto out;
  88        }
  89
  90        err = 0;
  91out:
  92        fclose(fp);
  93        return err;
  94}
  95
  96void strlist__remove(struct strlist *slist, struct str_node *snode)
  97{
  98        rblist__remove_node(&slist->rblist, &snode->rb_node);
  99}
 100
 101struct str_node *strlist__find(struct strlist *slist, const char *entry)
 102{
 103        struct str_node *snode = NULL;
 104        struct rb_node *rb_node = rblist__find(&slist->rblist, entry);
 105
 106        if (rb_node)
 107                snode = container_of(rb_node, struct str_node, rb_node);
 108
 109        return snode;
 110}
 111
 112static int strlist__parse_list_entry(struct strlist *slist, const char *s,
 113                                     const char *subst_dir)
 114{
 115        int err;
 116        char *subst = NULL;
 117
 118        if (strncmp(s, "file://", 7) == 0)
 119                return strlist__load(slist, s + 7);
 120
 121        if (subst_dir) {
 122                err = -ENOMEM;
 123                if (asprintf(&subst, "%s/%s", subst_dir, s) < 0)
 124                        goto out;
 125
 126                if (access(subst, F_OK) == 0) {
 127                        err = strlist__load(slist, subst);
 128                        goto out;
 129                }
 130
 131                if (slist->file_only) {
 132                        err = -ENOENT;
 133                        goto out;
 134                }
 135        }
 136
 137        err = strlist__add(slist, s);
 138out:
 139        free(subst);
 140        return err;
 141}
 142
 143static int strlist__parse_list(struct strlist *slist, const char *s, const char *subst_dir)
 144{
 145        char *sep;
 146        int err;
 147
 148        while ((sep = strchr(s, ',')) != NULL) {
 149                *sep = '\0';
 150                err = strlist__parse_list_entry(slist, s, subst_dir);
 151                *sep = ',';
 152                if (err != 0)
 153                        return err;
 154                s = sep + 1;
 155        }
 156
 157        return *s ? strlist__parse_list_entry(slist, s, subst_dir) : 0;
 158}
 159
 160struct strlist *strlist__new(const char *list, const struct strlist_config *config)
 161{
 162        struct strlist *slist = malloc(sizeof(*slist));
 163
 164        if (slist != NULL) {
 165                bool dupstr = true;
 166                bool file_only = false;
 167                const char *dirname = NULL;
 168
 169                if (config) {
 170                        dupstr = !config->dont_dupstr;
 171                        dirname = config->dirname;
 172                        file_only = config->file_only;
 173                }
 174
 175                rblist__init(&slist->rblist);
 176                slist->rblist.node_cmp    = strlist__node_cmp;
 177                slist->rblist.node_new    = strlist__node_new;
 178                slist->rblist.node_delete = strlist__node_delete;
 179
 180                slist->dupstr    = dupstr;
 181                slist->file_only = file_only;
 182
 183                if (list && strlist__parse_list(slist, list, dirname) != 0)
 184                        goto out_error;
 185        }
 186
 187        return slist;
 188out_error:
 189        free(slist);
 190        return NULL;
 191}
 192
 193void strlist__delete(struct strlist *slist)
 194{
 195        if (slist != NULL)
 196                rblist__delete(&slist->rblist);
 197}
 198
 199struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)
 200{
 201        struct str_node *snode = NULL;
 202        struct rb_node *rb_node;
 203
 204        rb_node = rblist__entry(&slist->rblist, idx);
 205        if (rb_node)
 206                snode = container_of(rb_node, struct str_node, rb_node);
 207
 208        return snode;
 209}
 210