Merge branch 'fasync-helper'
[pandora-kernel.git] / tools / perf / util / strlist.c
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
13 static 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
28 out_delete:
29         free(self);
30         return NULL;
31 }
32
33 static void str_node__delete(struct str_node *self, bool dupstr)
34 {
35         if (dupstr)
36                 free((void *)self->s);
37         free(self);
38 }
39
40 int 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
72 int 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;
94 out:
95         fclose(fp);
96         return err;
97 }
98
99 void 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
105 struct str_node *strlist__find(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 sn;
124         }
125
126         return NULL;
127 }
128
129 static 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
137 int 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
154 struct 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;
167 out_error:
168         free(self);
169         return NULL;
170 }
171
172 void 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
188 struct 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 }