]> bbs.cooldavid.org Git - net-next-2.6.git/blob - tools/perf/util/strlist.c
perf report: Add --dsos parameter
[net-next-2.6.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
68         return 0;
69 }
70
71 int strlist__load(struct strlist *self, const char *filename)
72 {
73         char entry[1024];
74         int err;
75         FILE *fp = fopen(filename, "r");
76
77         if (fp == NULL)
78                 return errno;
79
80         while (fgets(entry, sizeof(entry), fp) != NULL) {
81                 const size_t len = strlen(entry);
82
83                 if (len == 0)
84                         continue;
85                 entry[len - 1] = '\0';
86
87                 err = strlist__add(self, entry);
88                 if (err != 0)
89                         goto out;
90         }
91
92         err = 0;
93 out:
94         fclose(fp);
95         return err;
96 }
97
98 void strlist__remove(struct strlist *self, struct str_node *sn)
99 {
100         rb_erase(&sn->rb_node, &self->entries);
101         str_node__delete(sn, self->dupstr);
102 }
103
104 bool strlist__has_entry(struct strlist *self, const char *entry)
105 {
106         struct rb_node **p = &self->entries.rb_node;
107         struct rb_node *parent = NULL;
108
109         while (*p != NULL) {
110                 struct str_node *sn;
111                 int rc;
112
113                 parent = *p;
114                 sn = rb_entry(parent, struct str_node, rb_node);
115                 rc = strcmp(sn->s, entry);
116
117                 if (rc > 0)
118                         p = &(*p)->rb_left;
119                 else if (rc < 0)
120                         p = &(*p)->rb_right;
121                 else
122                         return true;
123         }
124
125         return false;
126 }
127
128 static int strlist__parse_list_entry(struct strlist *self, const char *s)
129 {
130         if (strncmp(s, "file://", 7) == 0)
131                 return strlist__load(self, s + 7);
132
133         return strlist__add(self, s);
134 }
135
136 int strlist__parse_list(struct strlist *self, const char *s)
137 {
138         char *sep;
139         int err;
140
141         while ((sep = strchr(s, ',')) != NULL) {
142                 *sep = '\0';
143                 err = strlist__parse_list_entry(self, s);
144                 *sep = ',';
145                 if (err != 0)
146                         return err;
147                 s = sep + 1;
148         }
149
150         return *s ? strlist__parse_list_entry(self, s) : 0;
151 }
152
153 struct strlist *strlist__new(bool dupstr, const char *slist)
154 {
155         struct strlist *self = malloc(sizeof(*self));
156
157         if (self != NULL) {
158                 self->entries = RB_ROOT;
159                 self->dupstr = dupstr;
160                 if (slist && strlist__parse_list(self, slist) != 0)
161                         goto out_error;
162         }
163
164         return self;
165 out_error:
166         free(self);
167         return NULL;
168 }
169
170 void strlist__delete(struct strlist *self)
171 {
172         if (self != NULL) {
173                 struct str_node *pos;
174                 struct rb_node *next = rb_first(&self->entries);
175
176                 while (next) {
177                         pos = rb_entry(next, struct str_node, rb_node);
178                         next = rb_next(&pos->rb_node);
179                         strlist__remove(self, pos);
180                 }
181                 self->entries = RB_ROOT;
182                 free(self);
183         }
184 }