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:
258
lib/roken/rtbl.c
258
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).
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -49,12 +49,16 @@ struct column_data {
|
||||
unsigned flags;
|
||||
size_t num_rows;
|
||||
struct column_entry *rows;
|
||||
unsigned int column_id;
|
||||
char *suffix;
|
||||
};
|
||||
|
||||
struct rtbl_data {
|
||||
char *column_prefix;
|
||||
size_t num_columns;
|
||||
struct column_data **columns;
|
||||
unsigned int flags;
|
||||
char *column_separator;
|
||||
};
|
||||
|
||||
rtbl_t
|
||||
@@ -63,6 +67,28 @@ rtbl_create (void)
|
||||
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 *
|
||||
rtbl_get_column (rtbl_t table, const char *column)
|
||||
{
|
||||
@@ -86,15 +112,18 @@ rtbl_destroy (rtbl_t table)
|
||||
free (c->rows);
|
||||
free (c->header);
|
||||
free (c->prefix);
|
||||
free (c->suffix);
|
||||
free (c);
|
||||
}
|
||||
free (table->column_prefix);
|
||||
free (table->column_separator);
|
||||
free (table->columns);
|
||||
free (table);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -110,25 +139,64 @@ rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
|
||||
free (col);
|
||||
return ENOMEM;
|
||||
}
|
||||
col->prefix = NULL;
|
||||
col->width = 0;
|
||||
col->flags = flags;
|
||||
col->prefix = NULL;
|
||||
col->width = 0;
|
||||
col->flags = flags;
|
||||
col->num_rows = 0;
|
||||
col->rows = NULL;
|
||||
col->rows = NULL;
|
||||
col->column_id = id;
|
||||
col->suffix = NULL;
|
||||
table->columns[table->num_columns++] = col;
|
||||
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
|
||||
column_compute_width (struct column_data *column)
|
||||
column_compute_width (rtbl_t table, struct column_data *column)
|
||||
{
|
||||
int i;
|
||||
|
||||
column->width = strlen (column->header);
|
||||
if(table->flags & RTBL_HEADER_STYLE_NONE)
|
||||
column->width = 0;
|
||||
else
|
||||
column->width = strlen (column->header);
|
||||
for (i = 0; i < column->num_rows; i++)
|
||||
column->width = max (column->width, strlen (column->rows[i].data));
|
||||
}
|
||||
|
||||
/* DEPRECATED */
|
||||
int
|
||||
rtbl_set_prefix (rtbl_t table, const char *prefix)
|
||||
{
|
||||
@@ -140,6 +208,17 @@ rtbl_set_prefix (rtbl_t table, const char *prefix)
|
||||
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
|
||||
rtbl_set_column_prefix (rtbl_t table, const char *column,
|
||||
const char *prefix)
|
||||
@@ -156,6 +235,36 @@ rtbl_set_column_prefix (rtbl_t table, const char *column,
|
||||
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 *
|
||||
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 "";
|
||||
}
|
||||
|
||||
int
|
||||
rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
|
||||
static const char *
|
||||
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_data *c = rtbl_get_column (table, column);
|
||||
|
||||
if (c == NULL)
|
||||
return -1;
|
||||
|
||||
row.data = strdup (data);
|
||||
if (row.data == NULL)
|
||||
return ENOMEM;
|
||||
@@ -192,24 +304,56 @@ rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
|
||||
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
|
||||
rtbl_format (rtbl_t table, FILE * f)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < table->num_columns; i++)
|
||||
column_compute_width (table->columns[i]);
|
||||
for (i = 0; i < table->num_columns; i++) {
|
||||
struct column_data *c = 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++) {
|
||||
struct column_data *c = table->columns[i];
|
||||
|
||||
fprintf (f, "%s", get_column_prefix (table, c));
|
||||
fprintf (f, "%-*s", (int)c->width, c->header);
|
||||
if(table->column_separator != NULL && i > 0)
|
||||
fprintf (f, "%s", table->column_separator);
|
||||
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", get_column_suffix (table, c));
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
|
||||
for (j = 0;; j++) {
|
||||
int flag = 0;
|
||||
|
||||
/* are there any more rows left? */
|
||||
for (i = 0; flag == 0 && i < table->num_columns; ++i) {
|
||||
struct column_data *c = table->columns[i];
|
||||
|
||||
@@ -225,15 +369,24 @@ rtbl_format (rtbl_t table, FILE * f)
|
||||
int w;
|
||||
struct column_data *c = table->columns[i];
|
||||
|
||||
if(table->column_separator != NULL && i > 0)
|
||||
fprintf (f, "%s", table->column_separator);
|
||||
|
||||
w = c->width;
|
||||
|
||||
if ((c->flags & RTBL_ALIGN_RIGHT) == 0)
|
||||
w = -w;
|
||||
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;
|
||||
}
|
||||
fprintf (f, "%s", get_column_prefix (table, c));
|
||||
if (c->num_rows <= j)
|
||||
fprintf (f, "%*s", w, "");
|
||||
else
|
||||
fprintf (f, "%*s", w, c->rows[j].data);
|
||||
fprintf (f, "%s", get_column_suffix (table, c));
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
@@ -245,36 +398,57 @@ int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
rtbl_t table;
|
||||
unsigned int a, b, c, d;
|
||||
|
||||
table = rtbl_create ();
|
||||
rtbl_add_column (table, "Issued", 0, &a);
|
||||
rtbl_add_column (table, "Expires", 0, &b);
|
||||
rtbl_add_column (table, "Foo", RTBL_ALIGN_RIGHT, &d);
|
||||
rtbl_add_column (table, "Principal", 0, &c);
|
||||
rtbl_add_column_by_id (table, 0, "Issued", 0);
|
||||
rtbl_add_column_by_id (table, 1, "Expires", 0);
|
||||
rtbl_add_column_by_id (table, 2, "Foo", RTBL_ALIGN_RIGHT);
|
||||
rtbl_add_column_by_id (table, 3, "Principal", 0);
|
||||
|
||||
rtbl_add_column_entry (table, a, "Jul 7 21:19:29");
|
||||
rtbl_add_column_entry (table, b, "Jul 8 07:19:29");
|
||||
rtbl_add_column_entry (table, d, "73");
|
||||
rtbl_add_column_entry (table, d, "0");
|
||||
rtbl_add_column_entry (table, d, "-2000");
|
||||
rtbl_add_column_entry (table, c, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
|
||||
rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
|
||||
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||
rtbl_add_column_entry_by_id (table, 2, "73");
|
||||
rtbl_add_column_entry_by_id (table, 2, "0");
|
||||
rtbl_add_column_entry_by_id (table, 2, "-2000");
|
||||
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 (table, b, "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, 0, "Jul 7 21:19:29");
|
||||
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||
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 (table, b, "Jul 8 07:19:29");
|
||||
rtbl_add_column_entry (table, c, "afs@NADA.KTH.SE");
|
||||
rtbl_add_column_entry_by_id (table, 0, "Jul 7 21:19:29");
|
||||
rtbl_add_column_entry_by_id (table, 1, "Jul 8 07:19:29");
|
||||
rtbl_add_column_entry_by_id (table, 3, "afs@NADA.KTH.SE");
|
||||
|
||||
rtbl_set_prefix (table, " ");
|
||||
rtbl_set_column_prefix (table, a, "");
|
||||
rtbl_set_separator (table, " ");
|
||||
|
||||
rtbl_format (table, stdout);
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user