mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git
synced 2024-11-15 00:04:23 +08:00
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>
This commit is contained in:
parent
83b419eb90
commit
ba24cf8498
@ -16,7 +16,9 @@
|
||||
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "common/sort-utils.h"
|
||||
#include "common/messages.h"
|
||||
|
||||
int compare_init(struct compare *comp, const struct sortdef *sortdef)
|
||||
{
|
||||
@ -55,3 +57,157 @@ int compare_add_sort_key(struct compare *comp, const char *key)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append given sort by its @id from associated sortdef.
|
||||
*
|
||||
* Return: 0 if id is valid
|
||||
* -1 if id not in sortdef
|
||||
*/
|
||||
int compare_add_sort_id(struct compare *comp, int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
if (id < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < SORT_MAX_KEYS; i++) {
|
||||
if (comp->sortdef[i].name == NULL)
|
||||
return -1;
|
||||
if (comp->sortdef[i].id == id) {
|
||||
comp->comp[comp->count] = comp->sortdef[i].comp;
|
||||
comp->count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Consume word-like list of key names (coma separated) and return its id if
|
||||
* found in sortdef. The @next pointer is advanced to the next expected key start.
|
||||
* Empty and NULL @next is accepted.
|
||||
*
|
||||
* Key lookup is case insensitive.
|
||||
*
|
||||
* Retrun: id from sortdef if a matching
|
||||
* -1 on error
|
||||
* -2 end of buffer
|
||||
*/
|
||||
int compare_parse_key_to_id(const struct compare *comp, const char **next)
|
||||
{
|
||||
const char *tmp = *next, *start = *next;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
/* No sort string (use defaults), or last. */
|
||||
if (!*next || !**next)
|
||||
return -2;
|
||||
|
||||
do {
|
||||
/* End of word. */
|
||||
if (*tmp == ',' || *tmp == 0) {
|
||||
/* Look up in sortdef. */
|
||||
for (int i = 0; comp->sortdef[i].name; i++) {
|
||||
int len = strlen(comp->sortdef[i].name);
|
||||
|
||||
if (strncasecmp(start, comp->sortdef[i].name, len) == 0) {
|
||||
/* Point to last NUL. */
|
||||
*next = tmp;
|
||||
/* Or the next valid char. */
|
||||
if (*tmp)
|
||||
(*next)++;
|
||||
return comp->sortdef[i].id;
|
||||
}
|
||||
}
|
||||
/* Not found, report which one. */
|
||||
*next = start;
|
||||
return -1;
|
||||
}
|
||||
/* Invalid char found. */
|
||||
if (!isalnum(*tmp)) {
|
||||
*next = tmp;
|
||||
return -1;
|
||||
}
|
||||
tmp++;
|
||||
} while(1);
|
||||
|
||||
/* Not found. */
|
||||
*next = start;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read id of its associated sort @key. Key lookup is case insensitive. */
|
||||
int compare_key_id(const struct compare *comp, const char *key)
|
||||
{
|
||||
if (!comp->sortdef)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (strcasecmp(comp->sortdef[i].name, key) == 0)
|
||||
return comp->sortdef[i].id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read sort key name associated to @id. */
|
||||
const char *compare_id_name(const struct compare *comp, int id)
|
||||
{
|
||||
if (!comp->sortdef)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (comp->sortdef[i].id == id)
|
||||
return comp->sortdef[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given @id (must exist in the associated sortdef) enabled in
|
||||
* @comp.
|
||||
*/
|
||||
bool compare_has_id(const struct compare *comp, int id)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!comp->sortdef)
|
||||
return false;
|
||||
|
||||
idx = -1;
|
||||
for (int i = 0; comp->sortdef[i].name; i++)
|
||||
if (comp->sortdef[i].id == id)
|
||||
idx = i;
|
||||
|
||||
if (idx < 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < comp->count; i++)
|
||||
if (comp->comp[i] == comp->sortdef[idx].comp)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up compare structure with associated sortdef from a user specified list
|
||||
* of keys.
|
||||
*/
|
||||
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def)
|
||||
{
|
||||
const char *tmp;
|
||||
int id;
|
||||
|
||||
tmp = def;
|
||||
do {
|
||||
id = compare_parse_key_to_id(comp, &tmp);
|
||||
if (id == -1) {
|
||||
error("unknown sort key: %s", tmp);
|
||||
return -1;
|
||||
}
|
||||
compare_add_sort_id(comp, id);
|
||||
} while (id >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef __COMMON_SORT_UTILS_H__
|
||||
#define __COMMON_SORT_UTILS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Example:
|
||||
|
||||
@ -48,7 +50,7 @@ void test() {
|
||||
.desc = "sort by id" },
|
||||
{ .name = "size", .comp = (sort_cmp_t)cmp_entry_size,
|
||||
.desc = "sort by entry size" },
|
||||
{ .name = NULL, .comp = NULL }
|
||||
SORTDEF_END
|
||||
};
|
||||
// List of keys to use for sort (e.g. from command line options)
|
||||
const char *sortby[] = { "size", "id" };
|
||||
@ -66,6 +68,9 @@ void test() {
|
||||
}
|
||||
*/
|
||||
|
||||
#define SORTDEF_END { .name = NULL, .comp = NULL }
|
||||
#define SORT_MAX_KEYS 32
|
||||
|
||||
typedef int (*sort_cmp_t)(const void *a, const void *b);
|
||||
typedef int (*sort_r_cmp_t)(const void *a, const void *b, void *data);
|
||||
|
||||
@ -73,10 +78,12 @@ struct sortdef {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
sort_cmp_t comp;
|
||||
/* User defined identifier of this sort key. */
|
||||
int id;
|
||||
};
|
||||
|
||||
struct compare {
|
||||
sort_cmp_t comp[32];
|
||||
sort_cmp_t comp[SORT_MAX_KEYS];
|
||||
unsigned long invert_map;
|
||||
int count;
|
||||
const struct sortdef *sortdef;
|
||||
@ -85,5 +92,11 @@ struct compare {
|
||||
int compare_init(struct compare *comp, const struct sortdef *sortdef);
|
||||
int compare_cmp_multi(const void *a, const void *b, const struct compare *comp);
|
||||
int compare_add_sort_key(struct compare *comp, const char *key);
|
||||
int compare_parse_key_to_id(const struct compare *comp, const char **next);
|
||||
int compare_add_sort_id(struct compare *comp, int id);
|
||||
int compare_key_id(const struct compare *comp, const char *key);
|
||||
const char *compare_id_name(const struct compare *comp, int id);
|
||||
bool compare_has_id(const struct compare *comp, int id);
|
||||
int compare_setup_sort(struct compare *comp, const struct sortdef *sdef, const char *def);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user