rtbl.c revision 103423
1310419Sdelphij/*
2285612Sdelphij * Copyright (c) 2000, 2002 Kungliga Tekniska H�gskolan
3285612Sdelphij * (Royal Institute of Technology, Stockholm, Sweden).
4285612Sdelphij * All rights reserved.
555857Ssheldonh *
655857Ssheldonh * Redistribution and use in source and binary forms, with or without
755857Ssheldonh * modification, are permitted provided that the following conditions
8310419Sdelphij * are met:
9285612Sdelphij *
10285612Sdelphij * 1. Redistributions of source code must retain the above copyright
1155857Ssheldonh *    notice, this list of conditions and the following disclaimer.
1255857Ssheldonh *
1355857Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright
1455857Ssheldonh *    notice, this list of conditions and the following disclaimer in the
1555857Ssheldonh *    documentation and/or other materials provided with the distribution.
16285612Sdelphij *
17285612Sdelphij * 3. Neither the name of the Institute nor the names of its contributors
18285612Sdelphij *    may be used to endorse or promote products derived from this software
19285612Sdelphij *    without specific prior written permission.
20285612Sdelphij *
21285612Sdelphij * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255857Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2382501Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455857Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25285612Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26285612Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27285612Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28285612Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29285612Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30285612Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31285612Sdelphij * SUCH DAMAGE.
32285612Sdelphij */
33285612Sdelphij
34285612Sdelphij#ifdef HAVE_CONFIG_H
35285612Sdelphij#include <config.h>
36285612SdelphijRCSID ("$Id: rtbl.c,v 1.4 2002/09/04 21:25:09 joda Exp $");
3782501Ssheldonh#endif
3855857Ssheldonh#include "roken.h"
39285612Sdelphij#include "rtbl.h"
40285612Sdelphij
41285612Sdelphijstruct column_entry {
4282501Ssheldonh    char *data;
4382501Ssheldonh};
4455857Ssheldonh
4582501Ssheldonhstruct column_data {
4682501Ssheldonh    char *header;
4782501Ssheldonh    char *prefix;
4882501Ssheldonh    int width;
4982501Ssheldonh    unsigned flags;
5055857Ssheldonh    size_t num_rows;
5182501Ssheldonh    struct column_entry *rows;
5282501Ssheldonh};
5382501Ssheldonh
5455857Ssheldonhstruct rtbl_data {
5599968Scharnier    char *column_prefix;
5655857Ssheldonh    size_t num_columns;
5799968Scharnier    struct column_data **columns;
5882501Ssheldonh};
5955857Ssheldonh
60285612Sdelphijrtbl_t
6182501Ssheldonhrtbl_create (void)
6282501Ssheldonh{
6382501Ssheldonh    return calloc (1, sizeof (struct rtbl_data));
6482501Ssheldonh}
6582501Ssheldonh
6699968Scharnierstatic struct column_data *
6755857Ssheldonhrtbl_get_column (rtbl_t table, const char *column)
6899968Scharnier{
6982501Ssheldonh    int i;
7082501Ssheldonh    for(i = 0; i < table->num_columns; i++)
7182501Ssheldonh	if(strcmp(table->columns[i]->header, column) == 0)
7282501Ssheldonh	    return table->columns[i];
7382501Ssheldonh    return NULL;
7482501Ssheldonh}
7582501Ssheldonh
7682501Ssheldonhvoid
7782501Ssheldonhrtbl_destroy (rtbl_t table)
7882501Ssheldonh{
7982501Ssheldonh    int i, j;
8082501Ssheldonh
8182501Ssheldonh    for (i = 0; i < table->num_columns; i++) {
8282501Ssheldonh	struct column_data *c = table->columns[i];
8382501Ssheldonh
8482501Ssheldonh	for (j = 0; j < c->num_rows; j++)
8582501Ssheldonh	    free (c->rows[j].data);
8682501Ssheldonh	free (c->rows);
8782501Ssheldonh	free (c->header);
8882501Ssheldonh	free (c->prefix);
8982501Ssheldonh	free (c);
9082501Ssheldonh    }
9182501Ssheldonh    free (table->column_prefix);
9255857Ssheldonh    free (table->columns);
9399968Scharnier    free (table);
9482501Ssheldonh}
9555857Ssheldonh
96285612Sdelphijint
97285612Sdelphijrtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
9855857Ssheldonh{
9955857Ssheldonh    struct column_data *col, **tmp;
100285612Sdelphij
10182501Ssheldonh    tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp));
10282501Ssheldonh    if (tmp == NULL)
10368965Sru	return ENOMEM;
10455857Ssheldonh    table->columns = tmp;
105285612Sdelphij    col = malloc (sizeof (*col));
10682501Ssheldonh    if (col == NULL)
10782501Ssheldonh	return ENOMEM;
10855857Ssheldonh    col->header = strdup (header);
10955857Ssheldonh    if (col->header == NULL) {
11055857Ssheldonh	free (col);
11182501Ssheldonh	return ENOMEM;
11282501Ssheldonh    }
113285612Sdelphij    col->prefix   = NULL;
114285612Sdelphij    col->width    = 0;
11555857Ssheldonh    col->flags    = flags;
116285612Sdelphij    col->num_rows = 0;
11755857Ssheldonh    col->rows     = NULL;
118285612Sdelphij    table->columns[table->num_columns++] = col;
11982501Ssheldonh    return 0;
12082501Ssheldonh}
12182501Ssheldonh
12255857Ssheldonhstatic void
12382501Ssheldonhcolumn_compute_width (struct column_data *column)
12482501Ssheldonh{
12582501Ssheldonh    int i;
12699968Scharnier
12755857Ssheldonh    column->width = strlen (column->header);
12899968Scharnier    for (i = 0; i < column->num_rows; i++)
12955857Ssheldonh	column->width = max (column->width, strlen (column->rows[i].data));
13055857Ssheldonh}
13155857Ssheldonh
13255857Ssheldonhint
13357673Ssheldonhrtbl_set_prefix (rtbl_t table, const char *prefix)
13457673Ssheldonh{
13555857Ssheldonh    if (table->column_prefix)
13682501Ssheldonh	free (table->column_prefix);
13782501Ssheldonh    table->column_prefix = strdup (prefix);
13882501Ssheldonh    if (table->column_prefix == NULL)
139285612Sdelphij	return ENOMEM;
14055857Ssheldonh    return 0;
14155857Ssheldonh}
14282501Ssheldonh
14382501Ssheldonhint
144107311Srurtbl_set_column_prefix (rtbl_t table, const char *column,
14582501Ssheldonh			const char *prefix)
14682501Ssheldonh{
147285612Sdelphij    struct column_data *c = rtbl_get_column (table, column);
148285612Sdelphij
149285612Sdelphij    if (c == NULL)
150285612Sdelphij	return -1;
151285612Sdelphij    if (c->prefix)
152285612Sdelphij	free (c->prefix);
153285612Sdelphij    c->prefix = strdup (prefix);
154285612Sdelphij    if (c->prefix == NULL)
155285612Sdelphij	return ENOMEM;
156285612Sdelphij    return 0;
157285612Sdelphij}
158285612Sdelphij
159285612Sdelphij
160285612Sdelphijstatic const char *
161285612Sdelphijget_column_prefix (rtbl_t table, struct column_data *c)
162285612Sdelphij{
163285612Sdelphij    if (c == NULL)
164285612Sdelphij	return "";
165285612Sdelphij    if (c->prefix)
166285612Sdelphij	return c->prefix;
167285612Sdelphij    if (table->column_prefix)
168285612Sdelphij	return table->column_prefix;
169285612Sdelphij    return "";
170285612Sdelphij}
171285612Sdelphij
172285612Sdelphijint
17355857Ssheldonhrtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
17482501Ssheldonh{
17582501Ssheldonh    struct column_entry row, *tmp;
17682501Ssheldonh
17782501Ssheldonh    struct column_data *c = rtbl_get_column (table, column);
17882501Ssheldonh
17955857Ssheldonh    if (c == NULL)
18055857Ssheldonh	return -1;
181285612Sdelphij
18282501Ssheldonh    row.data = strdup (data);
183131531Sru    if (row.data == NULL)
184285612Sdelphij	return ENOMEM;
185285612Sdelphij    tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp));
186285612Sdelphij    if (tmp == NULL) {
18782501Ssheldonh	free (row.data);
18882501Ssheldonh	return ENOMEM;
18982501Ssheldonh    }
190285612Sdelphij    c->rows = tmp;
19160588Ssheldonh    c->rows[c->num_rows++] = row;
192285612Sdelphij    return 0;
193285612Sdelphij}
19455857Ssheldonh
19582501Ssheldonhint
19682501Ssheldonhrtbl_format (rtbl_t table, FILE * f)
19782501Ssheldonh{
19882501Ssheldonh    int i, j;
19982501Ssheldonh
20082501Ssheldonh    for (i = 0; i < table->num_columns; i++)
20182501Ssheldonh	column_compute_width (table->columns[i]);
20255857Ssheldonh    for (i = 0; i < table->num_columns; i++) {
203285612Sdelphij	struct column_data *c = table->columns[i];
204285612Sdelphij
205285612Sdelphij	fprintf (f, "%s", get_column_prefix (table, c));
20655857Ssheldonh	fprintf (f, "%-*s", (int)c->width, c->header);
20755857Ssheldonh    }
208285612Sdelphij    fprintf (f, "\n");
209285612Sdelphij
210285612Sdelphij    for (j = 0;; j++) {
21155857Ssheldonh	int flag = 0;
21282501Ssheldonh
21382501Ssheldonh	for (i = 0; flag == 0 && i < table->num_columns; ++i) {
21482501Ssheldonh	    struct column_data *c = table->columns[i];
21555857Ssheldonh
21682501Ssheldonh	    if (c->num_rows > j) {
21782501Ssheldonh		++flag;
21882501Ssheldonh		break;
21955857Ssheldonh	    }
22082501Ssheldonh	}
22182501Ssheldonh	if (flag == 0)
22282501Ssheldonh	    break;
22355857Ssheldonh
22455857Ssheldonh	for (i = 0; i < table->num_columns; i++) {
22555857Ssheldonh	    int w;
226285612Sdelphij	    struct column_data *c = table->columns[i];
227285612Sdelphij
228285612Sdelphij	    w = c->width;
229289999Sglebius
230289999Sglebius	    if ((c->flags & RTBL_ALIGN_RIGHT) == 0)
231289999Sglebius		w = -w;
232285612Sdelphij	    fprintf (f, "%s", get_column_prefix (table, c));
233285612Sdelphij	    if (c->num_rows <= j)
234285612Sdelphij		fprintf (f, "%*s", w, "");
235285612Sdelphij	    else
236285612Sdelphij		fprintf (f, "%*s", w, c->rows[j].data);
237285612Sdelphij	}
238285612Sdelphij	fprintf (f, "\n");
239285612Sdelphij    }
240285612Sdelphij    return 0;
241285612Sdelphij}
242285612Sdelphij
243285612Sdelphij#ifdef TEST
244285612Sdelphijint
245285612Sdelphijmain (int argc, char **argv)
246285612Sdelphij{
247285612Sdelphij    rtbl_t table;
248285612Sdelphij    unsigned int a, b, c, d;
24982501Ssheldonh
25082501Ssheldonh    table = rtbl_create ();
25182501Ssheldonh    rtbl_add_column (table, "Issued", 0, &a);
25282501Ssheldonh    rtbl_add_column (table, "Expires", 0, &b);
253285612Sdelphij    rtbl_add_column (table, "Foo", RTBL_ALIGN_RIGHT, &d);
25460588Ssheldonh    rtbl_add_column (table, "Principal", 0, &c);
25582501Ssheldonh
25655857Ssheldonh    rtbl_add_column_entry (table, a, "Jul  7 21:19:29");
25782501Ssheldonh    rtbl_add_column_entry (table, b, "Jul  8 07:19:29");
25882501Ssheldonh    rtbl_add_column_entry (table, d, "73");
259285612Sdelphij    rtbl_add_column_entry (table, d, "0");
260285612Sdelphij    rtbl_add_column_entry (table, d, "-2000");
26182501Ssheldonh    rtbl_add_column_entry (table, c, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
26282501Ssheldonh
263285612Sdelphij    rtbl_add_column_entry (table, a, "Jul  7 21:19:29");
264285612Sdelphij    rtbl_add_column_entry (table, b, "Jul  8 07:19:29");
265158688Spav    rtbl_add_column_entry (table, c, "afs/pdc.kth.se@NADA.KTH.SE");
266285612Sdelphij
267285612Sdelphij    rtbl_add_column_entry (table, a, "Jul  7 21:19:29");
268285612Sdelphij    rtbl_add_column_entry (table, b, "Jul  8 07:19:29");
269285612Sdelphij    rtbl_add_column_entry (table, c, "afs@NADA.KTH.SE");
270285612Sdelphij
271285612Sdelphij    rtbl_set_prefix (table, "  ");
272285612Sdelphij    rtbl_set_column_prefix (table, a, "");
273285612Sdelphij
274285612Sdelphij    rtbl_format (table, stdout);
275285612Sdelphij
276285612Sdelphij    rtbl_destroy (table);
277285612Sdelphij
278285612Sdelphij}
27955857Ssheldonh
28055857Ssheldonh#endif
28168965Sru