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