Commit 27d0fd410c3cee00ece2e55f4354a7a9ec1a6a6a

Authored by Arnaldo Carvalho de Melo
Committed by Ingo Molnar
1 parent 60c1baf124

strlist: Introduce strlist__entry and strlist__nr_entries methods

The strlist__entry method allows accessing strlists like an
array, will be used in the 'perf report' to access the first
entry.

We now keep the nr_entries so that we can check if we have just
one entry, will be used in 'perf report' to improve the output
by showing just at the top when we have just, say, one DSO.

While at it use nr_entries to optimize strlist__is_empty by not
using the far more costly rb_first based implementation.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <1247325517-12272-2-git-send-email-acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 2 changed files with 27 additions and 4 deletions Inline Diff

tools/perf/util/strlist.c
1 /* 1 /*
2 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> 2 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
3 * 3 *
4 * Licensed under the GPLv2. 4 * Licensed under the GPLv2.
5 */ 5 */
6 6
7 #include "strlist.h" 7 #include "strlist.h"
8 #include <errno.h> 8 #include <errno.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 #include <stdlib.h> 10 #include <stdlib.h>
11 #include <string.h> 11 #include <string.h>
12 12
13 static struct str_node *str_node__new(const char *s, bool dupstr) 13 static struct str_node *str_node__new(const char *s, bool dupstr)
14 { 14 {
15 struct str_node *self = malloc(sizeof(*self)); 15 struct str_node *self = malloc(sizeof(*self));
16 16
17 if (self != NULL) { 17 if (self != NULL) {
18 if (dupstr) { 18 if (dupstr) {
19 s = strdup(s); 19 s = strdup(s);
20 if (s == NULL) 20 if (s == NULL)
21 goto out_delete; 21 goto out_delete;
22 } 22 }
23 self->s = s; 23 self->s = s;
24 } 24 }
25 25
26 return self; 26 return self;
27 27
28 out_delete: 28 out_delete:
29 free(self); 29 free(self);
30 return NULL; 30 return NULL;
31 } 31 }
32 32
33 static void str_node__delete(struct str_node *self, bool dupstr) 33 static void str_node__delete(struct str_node *self, bool dupstr)
34 { 34 {
35 if (dupstr) 35 if (dupstr)
36 free((void *)self->s); 36 free((void *)self->s);
37 free(self); 37 free(self);
38 } 38 }
39 39
40 int strlist__add(struct strlist *self, const char *new_entry) 40 int strlist__add(struct strlist *self, const char *new_entry)
41 { 41 {
42 struct rb_node **p = &self->entries.rb_node; 42 struct rb_node **p = &self->entries.rb_node;
43 struct rb_node *parent = NULL; 43 struct rb_node *parent = NULL;
44 struct str_node *sn; 44 struct str_node *sn;
45 45
46 while (*p != NULL) { 46 while (*p != NULL) {
47 int rc; 47 int rc;
48 48
49 parent = *p; 49 parent = *p;
50 sn = rb_entry(parent, struct str_node, rb_node); 50 sn = rb_entry(parent, struct str_node, rb_node);
51 rc = strcmp(sn->s, new_entry); 51 rc = strcmp(sn->s, new_entry);
52 52
53 if (rc > 0) 53 if (rc > 0)
54 p = &(*p)->rb_left; 54 p = &(*p)->rb_left;
55 else if (rc < 0) 55 else if (rc < 0)
56 p = &(*p)->rb_right; 56 p = &(*p)->rb_right;
57 else 57 else
58 return -EEXIST; 58 return -EEXIST;
59 } 59 }
60 60
61 sn = str_node__new(new_entry, self->dupstr); 61 sn = str_node__new(new_entry, self->dupstr);
62 if (sn == NULL) 62 if (sn == NULL)
63 return -ENOMEM; 63 return -ENOMEM;
64 64
65 rb_link_node(&sn->rb_node, parent, p); 65 rb_link_node(&sn->rb_node, parent, p);
66 rb_insert_color(&sn->rb_node, &self->entries); 66 rb_insert_color(&sn->rb_node, &self->entries);
67 ++self->nr_entries;
67 68
68 return 0; 69 return 0;
69 } 70 }
70 71
71 int strlist__load(struct strlist *self, const char *filename) 72 int strlist__load(struct strlist *self, const char *filename)
72 { 73 {
73 char entry[1024]; 74 char entry[1024];
74 int err; 75 int err;
75 FILE *fp = fopen(filename, "r"); 76 FILE *fp = fopen(filename, "r");
76 77
77 if (fp == NULL) 78 if (fp == NULL)
78 return errno; 79 return errno;
79 80
80 while (fgets(entry, sizeof(entry), fp) != NULL) { 81 while (fgets(entry, sizeof(entry), fp) != NULL) {
81 const size_t len = strlen(entry); 82 const size_t len = strlen(entry);
82 83
83 if (len == 0) 84 if (len == 0)
84 continue; 85 continue;
85 entry[len - 1] = '\0'; 86 entry[len - 1] = '\0';
86 87
87 err = strlist__add(self, entry); 88 err = strlist__add(self, entry);
88 if (err != 0) 89 if (err != 0)
89 goto out; 90 goto out;
90 } 91 }
91 92
92 err = 0; 93 err = 0;
93 out: 94 out:
94 fclose(fp); 95 fclose(fp);
95 return err; 96 return err;
96 } 97 }
97 98
98 void strlist__remove(struct strlist *self, struct str_node *sn) 99 void strlist__remove(struct strlist *self, struct str_node *sn)
99 { 100 {
100 rb_erase(&sn->rb_node, &self->entries); 101 rb_erase(&sn->rb_node, &self->entries);
101 str_node__delete(sn, self->dupstr); 102 str_node__delete(sn, self->dupstr);
102 } 103 }
103 104
104 bool strlist__has_entry(struct strlist *self, const char *entry) 105 bool strlist__has_entry(struct strlist *self, const char *entry)
105 { 106 {
106 struct rb_node **p = &self->entries.rb_node; 107 struct rb_node **p = &self->entries.rb_node;
107 struct rb_node *parent = NULL; 108 struct rb_node *parent = NULL;
108 109
109 while (*p != NULL) { 110 while (*p != NULL) {
110 struct str_node *sn; 111 struct str_node *sn;
111 int rc; 112 int rc;
112 113
113 parent = *p; 114 parent = *p;
114 sn = rb_entry(parent, struct str_node, rb_node); 115 sn = rb_entry(parent, struct str_node, rb_node);
115 rc = strcmp(sn->s, entry); 116 rc = strcmp(sn->s, entry);
116 117
117 if (rc > 0) 118 if (rc > 0)
118 p = &(*p)->rb_left; 119 p = &(*p)->rb_left;
119 else if (rc < 0) 120 else if (rc < 0)
120 p = &(*p)->rb_right; 121 p = &(*p)->rb_right;
121 else 122 else
122 return true; 123 return true;
123 } 124 }
124 125
125 return false; 126 return false;
126 } 127 }
127 128
128 static int strlist__parse_list_entry(struct strlist *self, const char *s) 129 static int strlist__parse_list_entry(struct strlist *self, const char *s)
129 { 130 {
130 if (strncmp(s, "file://", 7) == 0) 131 if (strncmp(s, "file://", 7) == 0)
131 return strlist__load(self, s + 7); 132 return strlist__load(self, s + 7);
132 133
133 return strlist__add(self, s); 134 return strlist__add(self, s);
134 } 135 }
135 136
136 int strlist__parse_list(struct strlist *self, const char *s) 137 int strlist__parse_list(struct strlist *self, const char *s)
137 { 138 {
138 char *sep; 139 char *sep;
139 int err; 140 int err;
140 141
141 while ((sep = strchr(s, ',')) != NULL) { 142 while ((sep = strchr(s, ',')) != NULL) {
142 *sep = '\0'; 143 *sep = '\0';
143 err = strlist__parse_list_entry(self, s); 144 err = strlist__parse_list_entry(self, s);
144 *sep = ','; 145 *sep = ',';
145 if (err != 0) 146 if (err != 0)
146 return err; 147 return err;
147 s = sep + 1; 148 s = sep + 1;
148 } 149 }
149 150
150 return *s ? strlist__parse_list_entry(self, s) : 0; 151 return *s ? strlist__parse_list_entry(self, s) : 0;
151 } 152 }
152 153
153 struct strlist *strlist__new(bool dupstr, const char *slist) 154 struct strlist *strlist__new(bool dupstr, const char *slist)
154 { 155 {
155 struct strlist *self = malloc(sizeof(*self)); 156 struct strlist *self = malloc(sizeof(*self));
156 157
157 if (self != NULL) { 158 if (self != NULL) {
158 self->entries = RB_ROOT; 159 self->entries = RB_ROOT;
159 self->dupstr = dupstr; 160 self->dupstr = dupstr;
161 self->nr_entries = 0;
160 if (slist && strlist__parse_list(self, slist) != 0) 162 if (slist && strlist__parse_list(self, slist) != 0)
161 goto out_error; 163 goto out_error;
162 } 164 }
163 165
164 return self; 166 return self;
165 out_error: 167 out_error:
166 free(self); 168 free(self);
167 return NULL; 169 return NULL;
168 } 170 }
169 171
170 void strlist__delete(struct strlist *self) 172 void strlist__delete(struct strlist *self)
171 { 173 {
172 if (self != NULL) { 174 if (self != NULL) {
173 struct str_node *pos; 175 struct str_node *pos;
174 struct rb_node *next = rb_first(&self->entries); 176 struct rb_node *next = rb_first(&self->entries);
175 177
176 while (next) { 178 while (next) {
177 pos = rb_entry(next, struct str_node, rb_node); 179 pos = rb_entry(next, struct str_node, rb_node);
178 next = rb_next(&pos->rb_node); 180 next = rb_next(&pos->rb_node);
179 strlist__remove(self, pos); 181 strlist__remove(self, pos);
180 } 182 }
181 self->entries = RB_ROOT; 183 self->entries = RB_ROOT;
182 free(self); 184 free(self);
183 } 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;
184 } 200 }
185 201
tools/perf/util/strlist.h
1 #ifndef STRLIST_H_ 1 #ifndef STRLIST_H_
2 #define STRLIST_H_ 2 #define STRLIST_H_
3 3
4 #include <linux/rbtree.h> 4 #include <linux/rbtree.h>
5 #include <stdbool.h> 5 #include <stdbool.h>
6 6
7 struct str_node { 7 struct str_node {
8 struct rb_node rb_node; 8 struct rb_node rb_node;
9 const char *s; 9 const char *s;
10 }; 10 };
11 11
12 struct strlist { 12 struct strlist {
13 struct rb_root entries; 13 struct rb_root entries;
14 bool dupstr; 14 unsigned int nr_entries;
15 bool dupstr;
15 }; 16 };
16 17
17 struct strlist *strlist__new(bool dupstr, const char *slist); 18 struct strlist *strlist__new(bool dupstr, const char *slist);
18 void strlist__delete(struct strlist *self); 19 void strlist__delete(struct strlist *self);
19 20
20 void strlist__remove(struct strlist *self, struct str_node *sn); 21 void strlist__remove(struct strlist *self, struct str_node *sn);
21 int strlist__load(struct strlist *self, const char *filename); 22 int strlist__load(struct strlist *self, const char *filename);
22 int strlist__add(struct strlist *self, const char *str); 23 int strlist__add(struct strlist *self, const char *str);
23 24
25 struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
24 bool strlist__has_entry(struct strlist *self, const char *entry); 26 bool strlist__has_entry(struct strlist *self, const char *entry);
25 27
26 static inline bool strlist__empty(const struct strlist *self) 28 static inline bool strlist__empty(const struct strlist *self)
27 { 29 {
28 return rb_first(&self->entries) == NULL; 30 return self->nr_entries == 0;
31 }
32
33 static inline unsigned int strlist__nr_entries(const struct strlist *self)
34 {
35 return self->nr_entries;
29 } 36 }
30 37
31 int strlist__parse_list(struct strlist *self, const char *s); 38 int strlist__parse_list(struct strlist *self, const char *s);
32 #endif /* STRLIST_H_ */ 39 #endif /* STRLIST_H_ */
33 40