libsmartcols: add scols_sort_table()

* add pointer to column cmp() function [scols_column_set_cmpfunc()]

 * allow to store per-cell application private data
   (to make it possible to sort tables on data independent on cell
    output data) [scols_cell_set_userdata() ...]

 * make it possible to access line cell by column
   [scols_line_get_column_cell()]

Sort and cmp() stuff based on patches from Shakur Shams Mullick.

Co-Author: Shakur Shams Mullick <shakursmullick@gmail.com>
Signed-off-by: Shakur Shams Mullick <shakursmullick@gmail.com>
Signed-off-by: Karel Zak <kzak@redhat.com>

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2014-05-20 15:04:11 +02:00
parent 2832032772
commit 57a86f9bff
8 changed files with 179 additions and 2 deletions

View File

@ -4,9 +4,12 @@ libscols_cell
scols_cell_copy_content
scols_cell_get_color
scols_cell_get_data
scols_cell_get_userdata
scols_cell_refer_data
scols_cell_set_color
scols_cell_set_data
scols_cell_set_userdata
scols_cmpstr_cells
scols_reset_cell
</SECTION>
@ -22,6 +25,7 @@ scols_column_is_right
scols_column_is_strict_width
scols_column_is_tree
scols_column_is_trunc
scols_column_set_cmpfunc
scols_column_set_color
scols_column_set_flags
scols_column_set_whint
@ -49,6 +53,7 @@ scols_line_alloc_cells
scols_line_free_cells
scols_line_get_cell
scols_line_get_color
scols_line_get_column_cell
scols_line_get_ncells
scols_line_get_parent
scols_line_get_userdata
@ -118,6 +123,7 @@ scols_table_set_column_separator
scols_table_set_line_separator
scols_table_set_stream
scols_table_set_symbols
scols_sort_table
scols_unref_table
</SECTION>

View File

@ -55,7 +55,7 @@ int scols_reset_cell(struct libscols_cell *ce)
/**
* scols_cell_set_data:
* @ce: a pointer to a struct libscols_cell instance
* @str: user data
* @str: data (used for scols_printtable())
*
* Stores a copy of the @str in @ce.
*
@ -82,7 +82,7 @@ int scols_cell_set_data(struct libscols_cell *ce, const char *str)
/**
* scols_cell_refer_data:
* @ce: a pointer to a struct libscols_cell instance
* @str: user data
* @str: data (used for scols_printtable())
*
* Adds a reference to @str to @ce. The pointer is deallocated by
* scols_reset_cell() or scols_unref_line(). This function is mostly designed
@ -114,6 +114,66 @@ const char *scols_cell_get_data(const struct libscols_cell *ce)
return ce ? ce->data : NULL;
}
/**
* scols_cell_set_userdata:
* @ce: a pointer to a struct libscols_cell instance
* @data: private user data
*
* Returns: 0, a negative value in case of an error.
*/
int scols_cell_set_userdata(struct libscols_cell *ce, void *data)
{
assert(ce);
if (!ce)
return -EINVAL;
ce->userdata = data;
return 0;
}
/**
* scols_cell_get_userdata
*
* @ce: a pointer to a struct libscols_cell instance
*
* Returns: user data
*/
void *scols_cell_get_userdata(struct libscols_cell *ce)
{
return ce ? ce->userdata : NULL;
}
/**
* scols_cmpstr_cells:
* @a: pointer to cell
* @b: pointer to cell
*
* Compares cells data by strcmp(). The function is designed for
* scols_column_set_cmpfunc() and scols_sort_table().
*
* Returns: follows strcmp() return values.
*/
int scols_cmpstr_cells(struct libscols_cell *a,
struct libscols_cell *b,
__attribute__((__unused__)) void *data)
{
const char *adata, *bdata;
if (a == b)
return 0;
adata = scols_cell_get_data(a);
bdata = scols_cell_get_data(b);
if (adata == NULL && bdata == NULL)
return 0;
if (adata == NULL)
return -1;
if (bdata == NULL)
return 1;
return strcmp(adata, bdata);
}
/**
* scols_cell_set_color:
* @ce: a pointer to a struct libscols_cell instance
@ -179,5 +239,7 @@ int scols_cell_copy_content(struct libscols_cell *dest,
rc = scols_cell_set_data(dest, scols_cell_get_data(src));
if (!rc)
rc = scols_cell_set_color(dest, scols_cell_get_color(src));
if (!rc)
dest->userdata = src->userdata;
return rc;
}

View File

@ -238,6 +238,30 @@ const char *scols_column_get_color(struct libscols_column *cl)
return cl ? cl->color : NULL;
}
/**
* scols_column_set_cmpfunc:
* @cl: column
* @cmp: pointer to compare function
* @data: private data for cmp function
*
* Returns: 0, a negative value in case of an error.
*/
int scols_column_set_cmpfunc(struct libscols_column *cl,
int (*cmp)(struct libscols_cell *,
struct libscols_cell *,
void *),
void *data)
{
assert(cl);
if (!cl)
return -EINVAL;
cl->cmpfunc = cmp;
cl->cmpfunc_data = data;
return 0;
}
/**
* scols_column_is_trunc:
* @cl: a pointer to a struct libscols_column instance

View File

@ -116,6 +116,11 @@ extern const char *scols_cell_get_data(const struct libscols_cell *ce);
extern int scols_cell_set_color(struct libscols_cell *ce, const char *color);
extern const char *scols_cell_get_color(const struct libscols_cell *ce);
extern void *scols_cell_get_userdata(struct libscols_cell *ce);
extern int scols_cell_set_userdata(struct libscols_cell *ce, void *data);
extern int scols_cmpstr_cells(struct libscols_cell *a,
struct libscols_cell *b, void *data);
/* column.c */
extern int scols_column_is_tree(struct libscols_column *cl);
extern int scols_column_is_trunc(struct libscols_column *cl);
@ -135,6 +140,11 @@ extern struct libscols_cell *scols_column_get_header(struct libscols_column *cl)
extern int scols_column_set_color(struct libscols_column *cl, const char *color);
extern const char *scols_column_get_color(struct libscols_column *cl);
extern int scols_column_set_cmpfunc(struct libscols_column *cl,
int (*cmp)(struct libscols_cell *a,
struct libscols_cell *b, void *),
void *data);
/* line.c */
extern struct libscols_line *scols_new_line(void);
extern void scols_ref_line(struct libscols_line *ln);
@ -153,6 +163,9 @@ extern int scols_line_set_color(struct libscols_line *ln, const char *color);
extern const char *scols_line_get_color(struct libscols_line *ln);
extern size_t scols_line_get_ncells(struct libscols_line *ln);
extern struct libscols_cell *scols_line_get_cell(struct libscols_line *ln, size_t n);
extern struct libscols_cell *scols_line_get_column_cell(
struct libscols_line *ln,
struct libscols_column *cl);
extern int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data);
extern int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data);
extern struct libscols_line *scols_copy_line(struct libscols_line *ln);
@ -203,6 +216,8 @@ extern int scols_table_set_stream(struct libscols_table *tb, FILE *stream);
extern FILE *scols_table_get_stream(struct libscols_table *tb);
extern int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce);
extern int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl);
/* table_print.c */
extern int scols_print_table(struct libscols_table *tb);
extern int scols_print_table_to_string(struct libscols_table *tb, char **data);

View File

@ -6,9 +6,12 @@ global:
scols_cell_copy_content;
scols_cell_get_color;
scols_cell_get_data;
scols_cell_get_userdata;
scols_cell_refer_data;
scols_cell_set_color;
scols_cell_set_data;
scols_cell_set_userdata;
scols_cmpstr_cells;
scols_column_get_color;
scols_column_get_flags;
scols_column_get_header;
@ -18,6 +21,7 @@ global:
scols_column_is_strict_width;
scols_column_is_tree;
scols_column_is_trunc;
scols_column_set_cmpfunc;
scols_column_set_color;
scols_column_set_flags;
scols_column_set_whint;
@ -34,6 +38,7 @@ global:
scols_line_free_cells;
scols_line_get_cell;
scols_line_get_color;
scols_line_get_column_cell;
scols_line_get_ncells;
scols_line_get_parent;
scols_line_get_userdata;
@ -58,6 +63,7 @@ global:
scols_ref_table;
scols_reset_cell;
scols_reset_iter;
scols_sort_table;
scols_symbols_set_branch;
scols_symbols_set_right;
scols_symbols_set_vertical;

View File

@ -354,6 +354,25 @@ struct libscols_cell *scols_line_get_cell(struct libscols_line *ln,
return &ln->cells[n];
}
/**
* scols_line_get_column_cell:
* @ln: a pointer to a struct libscols_line instance
* @cl: pointer to cell
*
* Like scols_line_get_cell() by cell is referenced by column.
*
* Returns: the @n-th cell in @ln, NULL in case of an error.
*/
struct libscols_cell *scols_line_get_column_cell(
struct libscols_line *ln,
struct libscols_column *cl)
{
assert(ln);
assert(cl);
return scols_line_get_cell(ln, cl->seqnum);
}
/**
* scols_line_set_data:
* @ln: a pointer to a struct libscols_cell instance

View File

@ -63,6 +63,7 @@ struct libscols_symbols {
struct libscols_cell {
char *data;
char *color;
void *userdata;
};
@ -83,6 +84,11 @@ struct libscols_column {
int is_extreme;
char *color; /* default column color */
int (*cmpfunc)(struct libscols_cell *,
struct libscols_cell *,
void *); /* cells comparison function */
void *cmpfunc_data;
struct libscols_cell header;
struct list_head cl_columns;
};

View File

@ -977,3 +977,42 @@ char *scols_table_get_line_separator(struct libscols_table *tb)
return tb->linesep;
}
static int cells_cmp_wrapper(struct list_head *a, struct list_head *b, void *data)
{
struct libscols_column *cl = (struct libscols_column *) data;
struct libscols_line *ra, *rb;
struct libscols_cell *ca, *cb;
assert(a);
assert(b);
assert(cl);
ra = list_entry(a, struct libscols_line, ln_lines);
rb = list_entry(b, struct libscols_line, ln_lines);
ca = scols_line_get_cell(ra, cl->seqnum);
cb = scols_line_get_cell(rb, cl->seqnum);
return cl->cmpfunc(ca, cb, cl->cmpfunc_data);
}
/**
* scols_sort_table:
* @tb: table
* @cl: order by this column
*
* Orders the table by the column. See also scols_column_set_cmpfunc().
*
* Returns: 0, a negative value in case of an error.
*/
int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl)
{
assert(tb);
assert(cl);
if (!tb || !cl)
return -EINVAL;
list_sort(&tb->tb_lines, cells_cmp_wrapper, cl);
return 0;
}