root/tools/perf/util/strlist.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. strlist__node_new
  2. str_node__delete
  3. strlist__node_delete
  4. strlist__node_cmp
  5. strlist__add
  6. strlist__load
  7. strlist__remove
  8. strlist__find
  9. strlist__parse_list_entry
  10. strlist__parse_list
  11. strlist__new
  12. strlist__delete
  13. strlist__entry

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

/* [<][>][^][v][top][bottom][index][help] */