implement a bunch of stuff:
* column separator (instead of global column prefix) * per column suffix * indexing columns by id-number instead of column header * optional header supression (via settable flags) * ability to end a row * don't extend last column to full width git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@13982 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
236
lib/roken/rtbl.c
236
lib/roken/rtbl.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2002 Kungliga Tekniska H<>gskolan
|
* Copyright (c) 2000, 2002, 2004 Kungliga Tekniska H<>gskolan
|
||||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -49,12 +49,16 @@ struct column_data {
|
|||||||
unsigned flags;
|
unsigned flags;
|
||||||
size_t num_rows;
|
size_t num_rows;
|
||||||
struct column_entry *rows;
|
struct column_entry *rows;
|
||||||
|
unsigned int column_id;
|
||||||
|
char *suffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtbl_data {
|
struct rtbl_data {
|
||||||
char *column_prefix;
|
char *column_prefix;
|
||||||
size_t num_columns;
|
size_t num_columns;
|
||||||
struct column_data **columns;
|
struct column_data **columns;
|
||||||
|
unsigned int flags;
|
||||||
|
char *column_separator;
|
||||||
};
|
};
|
||||||
|
|
||||||
rtbl_t
|
rtbl_t
|
||||||
@@ -63,6 +67,28 @@ rtbl_create (void)
|
|||||||
return calloc (1, sizeof (struct rtbl_data));
|
return calloc (1, sizeof (struct rtbl_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rtbl_set_flags (rtbl_t table, unsigned int flags)
|
||||||
|
{
|
||||||
|
table->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
rtbl_get_flags (rtbl_t table)
|
||||||
|
{
|
||||||
|
return table->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct column_data *
|
||||||
|
rtbl_get_column_by_id (rtbl_t table, unsigned int id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < table->num_columns; i++)
|
||||||
|
if(table->columns[i]->column_id == id)
|
||||||
|
return table->columns[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct column_data *
|
static struct column_data *
|
||||||
rtbl_get_column (rtbl_t table, const char *column)
|
rtbl_get_column (rtbl_t table, const char *column)
|
||||||
{
|
{
|
||||||
@@ -86,15 +112,18 @@ rtbl_destroy (rtbl_t table)
|
|||||||
free (c->rows);
|
free (c->rows);
|
||||||
free (c->header);
|
free (c->header);
|
||||||
free (c->prefix);
|
free (c->prefix);
|
||||||
|
free (c->suffix);
|
||||||
free (c);
|
free (c);
|
||||||
}
|
}
|
||||||
free (table->column_prefix);
|
free (table->column_prefix);
|
||||||
|
free (table->column_separator);
|
||||||
free (table->columns);
|
free (table->columns);
|
||||||
free (table);
|
free (table);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
|
rtbl_add_column_by_id (rtbl_t table, unsigned int id,
|
||||||
|
const char *header, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct column_data *col, **tmp;
|
struct column_data *col, **tmp;
|
||||||
|
|
||||||
@@ -115,20 +144,59 @@ rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
|
|||||||
col->flags = flags;
|
col->flags = flags;
|
||||||
col->num_rows = 0;
|
col->num_rows = 0;
|
||||||
col->rows = NULL;
|
col->rows = NULL;
|
||||||
|
col->column_id = id;
|
||||||
|
col->suffix = NULL;
|
||||||
table->columns[table->num_columns++] = col;
|
table->columns[table->num_columns++] = col;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
|
||||||
|
{
|
||||||
|
return rtbl_add_column_by_id(table, 0, header, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtbl_new_row(rtbl_t);
|
||||||
|
int
|
||||||
|
rtbl_new_row(rtbl_t table)
|
||||||
|
{
|
||||||
|
size_t max_rows = 0;
|
||||||
|
size_t c;
|
||||||
|
for (c = 0; c < table->num_columns; c++)
|
||||||
|
if(table->columns[c]->num_rows > max_rows)
|
||||||
|
max_rows = table->columns[c]->num_rows;
|
||||||
|
for (c = 0; c < table->num_columns; c++) {
|
||||||
|
struct column_entry *tmp;
|
||||||
|
|
||||||
|
if(table->columns[c]->num_rows == max_rows)
|
||||||
|
continue;
|
||||||
|
tmp = realloc(table->columns[c]->rows,
|
||||||
|
max_rows * sizeof(table->columns[c]->rows));
|
||||||
|
if(tmp == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
table->columns[c]->rows = tmp;
|
||||||
|
while(table->columns[c]->num_rows < max_rows) {
|
||||||
|
if((tmp[table->columns[c]->num_rows++].data = strdup("")) == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
column_compute_width (struct column_data *column)
|
column_compute_width (rtbl_t table, struct column_data *column)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if(table->flags & RTBL_HEADER_STYLE_NONE)
|
||||||
|
column->width = 0;
|
||||||
|
else
|
||||||
column->width = strlen (column->header);
|
column->width = strlen (column->header);
|
||||||
for (i = 0; i < column->num_rows; i++)
|
for (i = 0; i < column->num_rows; i++)
|
||||||
column->width = max (column->width, strlen (column->rows[i].data));
|
column->width = max (column->width, strlen (column->rows[i].data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DEPRECATED */
|
||||||
int
|
int
|
||||||
rtbl_set_prefix (rtbl_t table, const char *prefix)
|
rtbl_set_prefix (rtbl_t table, const char *prefix)
|
||||||
{
|
{
|
||||||
@@ -140,6 +208,17 @@ rtbl_set_prefix (rtbl_t table, const char *prefix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtbl_set_separator (rtbl_t table, const char *separator)
|
||||||
|
{
|
||||||
|
if (table->column_separator)
|
||||||
|
free (table->column_separator);
|
||||||
|
table->column_separator = strdup (separator);
|
||||||
|
if (table->column_separator == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtbl_set_column_prefix (rtbl_t table, const char *column,
|
rtbl_set_column_prefix (rtbl_t table, const char *column,
|
||||||
const char *prefix)
|
const char *prefix)
|
||||||
@@ -156,6 +235,36 @@ rtbl_set_column_prefix (rtbl_t table, const char *column,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtbl_set_column_affix_by_id(rtbl_t table, unsigned int id,
|
||||||
|
const char *prefix, const char *suffix)
|
||||||
|
{
|
||||||
|
struct column_data *c = rtbl_get_column_by_id (table, id);
|
||||||
|
|
||||||
|
if (c == NULL)
|
||||||
|
return -1;
|
||||||
|
if (c->prefix)
|
||||||
|
free (c->prefix);
|
||||||
|
if(prefix == NULL)
|
||||||
|
c->prefix = NULL;
|
||||||
|
else {
|
||||||
|
c->prefix = strdup (prefix);
|
||||||
|
if (c->prefix == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->suffix)
|
||||||
|
free (c->suffix);
|
||||||
|
if(suffix == NULL)
|
||||||
|
c->suffix = NULL;
|
||||||
|
else {
|
||||||
|
c->suffix = strdup (suffix);
|
||||||
|
if (c->suffix == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_column_prefix (rtbl_t table, struct column_data *c)
|
get_column_prefix (rtbl_t table, struct column_data *c)
|
||||||
@@ -169,16 +278,19 @@ get_column_prefix (rtbl_t table, struct column_data *c)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static const char *
|
||||||
rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
|
get_column_suffix (rtbl_t table, struct column_data *c)
|
||||||
|
{
|
||||||
|
if (c && c->suffix)
|
||||||
|
return c->suffix;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
add_column_entry (struct column_data *c, const char *data)
|
||||||
{
|
{
|
||||||
struct column_entry row, *tmp;
|
struct column_entry row, *tmp;
|
||||||
|
|
||||||
struct column_data *c = rtbl_get_column (table, column);
|
|
||||||
|
|
||||||
if (c == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
row.data = strdup (data);
|
row.data = strdup (data);
|
||||||
if (row.data == NULL)
|
if (row.data == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
@@ -192,24 +304,56 @@ rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtbl_add_column_entry_by_id (rtbl_t table, unsigned int id, const char *data)
|
||||||
|
{
|
||||||
|
struct column_data *c = rtbl_get_column_by_id (table, id);
|
||||||
|
|
||||||
|
if (c == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return add_column_entry(c, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
|
||||||
|
{
|
||||||
|
struct column_data *c = rtbl_get_column (table, column);
|
||||||
|
|
||||||
|
if (c == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return add_column_entry(c, data);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rtbl_format (rtbl_t table, FILE * f)
|
rtbl_format (rtbl_t table, FILE * f)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < table->num_columns; i++)
|
for (i = 0; i < table->num_columns; i++)
|
||||||
column_compute_width (table->columns[i]);
|
column_compute_width (table, table->columns[i]);
|
||||||
|
if((table->flags & RTBL_HEADER_STYLE_NONE) == 0) {
|
||||||
for (i = 0; i < table->num_columns; i++) {
|
for (i = 0; i < table->num_columns; i++) {
|
||||||
struct column_data *c = table->columns[i];
|
struct column_data *c = table->columns[i];
|
||||||
|
|
||||||
|
if(table->column_separator != NULL && i > 0)
|
||||||
|
fprintf (f, "%s", table->column_separator);
|
||||||
fprintf (f, "%s", get_column_prefix (table, c));
|
fprintf (f, "%s", get_column_prefix (table, c));
|
||||||
|
if(i == table->num_columns - 1 && c->suffix == NULL)
|
||||||
|
/* last column, so no need to pad with spaces */
|
||||||
|
fprintf (f, "%-*s", 0, c->header);
|
||||||
|
else
|
||||||
fprintf (f, "%-*s", (int)c->width, c->header);
|
fprintf (f, "%-*s", (int)c->width, c->header);
|
||||||
|
fprintf (f, "%s", get_column_suffix (table, c));
|
||||||
}
|
}
|
||||||
fprintf (f, "\n");
|
fprintf (f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0;; j++) {
|
for (j = 0;; j++) {
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
|
|
||||||
|
/* are there any more rows left? */
|
||||||
for (i = 0; flag == 0 && i < table->num_columns; ++i) {
|
for (i = 0; flag == 0 && i < table->num_columns; ++i) {
|
||||||
struct column_data *c = table->columns[i];
|
struct column_data *c = table->columns[i];
|
||||||
|
|
||||||
@@ -225,15 +369,24 @@ rtbl_format (rtbl_t table, FILE * f)
|
|||||||
int w;
|
int w;
|
||||||
struct column_data *c = table->columns[i];
|
struct column_data *c = table->columns[i];
|
||||||
|
|
||||||
|
if(table->column_separator != NULL && i > 0)
|
||||||
|
fprintf (f, "%s", table->column_separator);
|
||||||
|
|
||||||
w = c->width;
|
w = c->width;
|
||||||
|
|
||||||
if ((c->flags & RTBL_ALIGN_RIGHT) == 0)
|
if ((c->flags & RTBL_ALIGN_RIGHT) == 0) {
|
||||||
|
if(i == table->num_columns - 1 && c->suffix == NULL)
|
||||||
|
/* last column, so no need to pad with spaces */
|
||||||
|
w = 0;
|
||||||
|
else
|
||||||
w = -w;
|
w = -w;
|
||||||
|
}
|
||||||
fprintf (f, "%s", get_column_prefix (table, c));
|
fprintf (f, "%s", get_column_prefix (table, c));
|
||||||
if (c->num_rows <= j)
|
if (c->num_rows <= j)
|
||||||
fprintf (f, "%*s", w, "");
|
fprintf (f, "%*s", w, "");
|
||||||
else
|
else
|
||||||
fprintf (f, "%*s", w, c->rows[j].data);
|
fprintf (f, "%*s", w, c->rows[j].data);
|
||||||
|
fprintf (f, "%s", get_column_suffix (table, c));
|
||||||
}
|
}
|
||||||
fprintf (f, "\n");
|
fprintf (f, "\n");
|
||||||
}
|
}
|
||||||
@@ -245,36 +398,57 @@ int
|
|||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
rtbl_t table;
|
rtbl_t table;
|
||||||
unsigned int a, b, c, d;
|
|
||||||
|
|
||||||
table = rtbl_create ();
|
table = rtbl_create ();
|
||||||
rtbl_add_column (table, "Issued", 0, &a);
|
rtbl_add_column_by_id (table, 0, "Issued", 0);
|
||||||
rtbl_add_column (table, "Expires", 0, &b);
|
rtbl_add_column_by_id (table, 1, "Expires", 0);
|
||||||
rtbl_add_column (table, "Foo", RTBL_ALIGN_RIGHT, &d);
|
rtbl_add_column_by_id (table, 2, "Foo", RTBL_ALIGN_RIGHT);
|
||||||
rtbl_add_column (table, "Principal", 0, &c);
|
rtbl_add_column_by_id (table, 3, "Principal", 0);
|
||||||
|
|
||||||
rtbl_add_column_entry (table, a, "Jul 7 21:19:29");
|
rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
|
||||||
rtbl_add_column_entry (table, b, "Jul 8 07:19:29");
|
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||||
rtbl_add_column_entry (table, d, "73");
|
rtbl_add_column_entry_by_id (table, 2, "73");
|
||||||
rtbl_add_column_entry (table, d, "0");
|
rtbl_add_column_entry_by_id (table, 2, "0");
|
||||||
rtbl_add_column_entry (table, d, "-2000");
|
rtbl_add_column_entry_by_id (table, 2, "-2000");
|
||||||
rtbl_add_column_entry (table, c, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
|
rtbl_add_column_entry_by_id (table, 3, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
|
||||||
|
|
||||||
rtbl_add_column_entry (table, a, "Jul 7 21:19:29");
|
rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
|
||||||
rtbl_add_column_entry (table, b, "Jul 8 07:19:29");
|
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||||
rtbl_add_column_entry (table, c, "afs/pdc.kth.se@NADA.KTH.SE");
|
rtbl_add_column_entry_by_id (table, 3, "afs/pdc.kth.se@NADA.KTH.SE");
|
||||||
|
|
||||||
rtbl_add_column_entry (table, a, "Jul 7 21:19:29");
|
rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
|
||||||
rtbl_add_column_entry (table, b, "Jul 8 07:19:29");
|
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||||
rtbl_add_column_entry (table, c, "afs@NADA.KTH.SE");
|
rtbl_add_column_entry_by_id (table, 3, "afs@NADA.KTH.SE");
|
||||||
|
|
||||||
rtbl_set_prefix (table, " ");
|
rtbl_set_separator (table, " ");
|
||||||
rtbl_set_column_prefix (table, a, "");
|
|
||||||
|
|
||||||
rtbl_format (table, stdout);
|
rtbl_format (table, stdout);
|
||||||
|
|
||||||
rtbl_destroy (table);
|
rtbl_destroy (table);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
table = rtbl_create ();
|
||||||
|
rtbl_add_column_by_id (table, 0, "Column A", 0);
|
||||||
|
rtbl_set_column_affix_by_id (table, 0, "<", ">");
|
||||||
|
rtbl_add_column_by_id (table, 1, "Column B", 0);
|
||||||
|
rtbl_set_column_affix_by_id (table, 1, "[", "]");
|
||||||
|
rtbl_add_column_by_id (table, 2, "Column C", 0);
|
||||||
|
rtbl_set_column_affix_by_id (table, 2, "(", ")");
|
||||||
|
|
||||||
|
rtbl_add_column_entry_by_id (table, 0, "1");
|
||||||
|
rtbl_new_row(table);
|
||||||
|
rtbl_add_column_entry_by_id (table, 1, "2");
|
||||||
|
rtbl_new_row(table);
|
||||||
|
rtbl_add_column_entry_by_id (table, 2, "3");
|
||||||
|
rtbl_new_row(table);
|
||||||
|
|
||||||
|
rtbl_set_separator (table, " ");
|
||||||
|
rtbl_format (table, stdout);
|
||||||
|
|
||||||
|
rtbl_destroy (table);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user