Skip to content

Commit e8dcb3c

Browse files
committed
btrfs-progs: update sorting API
Add parsing of user defined sorting specification and some helpers. Example usage: sortdef = "key1,key2,key3" do { id = compare_parse_key_to_id(&comp, sortdef) if (id < 0) return error; compare_add_sort_id(&comp, id) } while(id >= 0); Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9592dfe commit e8dcb3c

File tree

2 files changed

+171
-2
lines changed

2 files changed

+171
-2
lines changed

common/sort-utils.c

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
#include <strings.h>
1818
#include <string.h>
19+
#include <ctype.h>
1920
#include "common/sort-utils.h"
21+
#include "common/messages.h"
2022

2123
int compare_init(struct compare *comp, const struct sortdef *sortdef)
2224
{
@@ -55,3 +57,157 @@ int compare_add_sort_key(struct compare *comp, const char *key)
5557
}
5658
return 0;
5759
}
60+
61+
/*
62+
* Append given sort by its @id from associated sortdef.
63+
*
64+
* Return: 0 if id is valid
65+
* -1 if id not in sortdef
66+
*/
67+
int compare_add_sort_id(struct compare *comp, int id)
68+
{
69+
int i;
70+
71+
if (!comp->sortdef)
72+
return -1;
73+
74+
if (id < 0)
75+
return -1;
76+
77+
for (i = 0; i < SORT_MAX_KEYS; i++) {
78+
if (comp->sortdef[i].name == NULL)
79+
return -1;
80+
if (comp->sortdef[i].id == id) {
81+
comp->comp[comp->count] = comp->sortdef[i].comp;
82+
comp->count++;
83+
break;
84+
}
85+
}
86+
return 0;
87+
}
88+
89+
/*
90+
* Consume word-like list of key names (coma separated) and return its id if
91+
* found in sortdef. The @next pointer is advanced to the next expected key start.
92+
* Empty and NULL @next is accepted.
93+
*
94+
* Key lookup is case insensitive.
95+
*
96+
* Retrun: id from sortdef if a matching
97+
* -1 on error
98+
* -2 end of buffer
99+
*/
100+
int compare_parse_key_to_id(const struct compare *comp, const char **next)
101+
{
102+
const char *tmp = *next, *start = *next;
103+
104+
if (!comp->sortdef)
105+
return -1;
106+
107+
/* No sort string (use defaults), or last. */
108+
if (!*next || !**next)
109+
return -2;
110+
111+
do {
112+
/* End of word. */
113+
if (*tmp == ',' || *tmp == 0) {
114+
/* Look up in sortdef. */
115+
for (int i = 0; comp->sortdef[i].name; i++) {
116+
int len = strlen(comp->sortdef[i].name);
117+
118+
if (strncasecmp(start, comp->sortdef[i].name, len) == 0) {
119+
/* Point to last NUL. */
120+
*next = tmp;
121+
/* Or the next valid char. */
122+
if (*tmp)
123+
(*next)++;
124+
return comp->sortdef[i].id;
125+
}
126+
}
127+
/* Not found, report which one. */
128+
*next = start;
129+
return -1;
130+
}
131+
/* Invalid char found. */
132+
if (!isalnum(*tmp)) {
133+
*next = tmp;
134+
return -1;
135+
}
136+
tmp++;
137+
} while(1);
138+
139+
/* Not found. */
140+
*next = start;
141+
return -1;
142+
}
143+
144+
/* Read id of its associated sort @key. Key lookup is case insensitive. */
145+
int compare_key_id(const struct compare *comp, const char *key)
146+
{
147+
if (!comp->sortdef)
148+
return -1;
149+
150+
for (int i = 0; comp->sortdef[i].name; i++)
151+
if (strcasecmp(comp->sortdef[i].name, key) == 0)
152+
return comp->sortdef[i].id;
153+
return -1;
154+
}
155+
156+
/* Read sort key name associated to @id. */
157+
const char *compare_id_name(const struct compare *comp, int id)
158+
{
159+
if (!comp->sortdef)
160+
return NULL;
161+
162+
for (int i = 0; comp->sortdef[i].name; i++)
163+
if (comp->sortdef[i].id == id)
164+
return comp->sortdef[i].name;
165+
return NULL;
166+
}
167+
168+
/*
169+
* Check if the given @id (must exist in the associated sortdef) enabled in
170+
* @comp.
171+
*/
172+
bool compare_has_id(const struct compare *comp, int id)
173+
{
174+
int idx;
175+
176+
if (!comp->sortdef)
177+
return false;
178+
179+
idx = -1;
180+
for (int i = 0; comp->sortdef[i].name; i++)
181+
if (comp->sortdef[i].id == id)
182+
idx = i;
183+
184+
if (idx < 0)
185+
return false;
186+
187+
for (int i = 0; i < comp->count; i++)
188+
if (comp->comp[i] == comp->sortdef[idx].comp)
189+
return true;
190+
return false;
191+
}
192+
193+
/*
194+
* Set up compare structure with associated sortdef from a user specified list
195+
* of keys.
196+
*/
197+
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def)
198+
{
199+
const char *tmp;
200+
int id;
201+
202+
tmp = def;
203+
do {
204+
id = compare_parse_key_to_id(comp, &tmp);
205+
if (id == -1) {
206+
error("unknown sort key: %s", tmp);
207+
return -1;
208+
}
209+
compare_add_sort_id(comp, id);
210+
} while (id >= 0);
211+
212+
return 0;
213+
}

common/sort-utils.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#ifndef __COMMON_SORT_UTILS_H__
1818
#define __COMMON_SORT_UTILS_H__
1919

20+
#include <stdbool.h>
21+
2022
/*
2123
* Example:
2224
@@ -48,7 +50,7 @@ void test() {
4850
.desc = "sort by id" },
4951
{ .name = "size", .comp = (sort_cmp_t)cmp_entry_size,
5052
.desc = "sort by entry size" },
51-
{ .name = NULL, .comp = NULL }
53+
SORTDEF_END
5254
};
5355
// List of keys to use for sort (e.g. from command line options)
5456
const char *sortby[] = { "size", "id" };
@@ -66,17 +68,22 @@ void test() {
6668
}
6769
*/
6870

71+
#define SORTDEF_END { .name = NULL, .comp = NULL }
72+
#define SORT_MAX_KEYS 32
73+
6974
typedef int (*sort_cmp_t)(const void *a, const void *b);
7075
typedef int (*sort_r_cmp_t)(const void *a, const void *b, void *data);
7176

7277
struct sortdef {
7378
const char *name;
7479
const char *desc;
7580
sort_cmp_t comp;
81+
/* User defined identifier of this sort key. */
82+
int id;
7683
};
7784

7885
struct compare {
79-
sort_cmp_t comp[32];
86+
sort_cmp_t comp[SORT_MAX_KEYS];
8087
unsigned long invert_map;
8188
int count;
8289
const struct sortdef *sortdef;
@@ -85,5 +92,11 @@ struct compare {
8592
int compare_init(struct compare *comp, const struct sortdef *sortdef);
8693
int compare_cmp_multi(const void *a, const void *b, const struct compare *comp);
8794
int compare_add_sort_key(struct compare *comp, const char *key);
95+
int compare_parse_key_to_id(const struct compare *comp, const char **next);
96+
int compare_add_sort_id(struct compare *comp, int id);
97+
int compare_key_id(const struct compare *comp, const char *key);
98+
const char *compare_id_name(const struct compare *comp, int id);
99+
bool compare_has_id(const struct compare *comp, int id);
100+
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def);
88101

89102
#endif

0 commit comments

Comments
 (0)