rtbl.c revision 72445
1/* 2 * Copyright (c) 2000 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifdef HAVE_CONFIG_H 35#include <config.h> 36RCSID ("$Id: rtbl.c,v 1.3 2000/07/20 14:42:31 assar Exp $"); 37#endif 38#include "roken.h" 39#include "rtbl.h" 40 41struct column_entry { 42 char *data; 43}; 44 45struct column_data { 46 char *header; 47 char *prefix; 48 int width; 49 unsigned flags; 50 size_t num_rows; 51 struct column_entry *rows; 52}; 53 54struct rtbl_data { 55 char *column_prefix; 56 size_t num_columns; 57 struct column_data **columns; 58}; 59 60rtbl_t 61rtbl_create (void) 62{ 63 return calloc (1, sizeof (struct rtbl_data)); 64} 65 66static struct column_data * 67rtbl_get_column (rtbl_t table, const char *column) 68{ 69 int i; 70 for(i = 0; i < table->num_columns; i++) 71 if(strcmp(table->columns[i]->header, column) == 0) 72 return table->columns[i]; 73 return NULL; 74} 75 76void 77rtbl_destroy (rtbl_t table) 78{ 79 int i, j; 80 81 for (i = 0; i < table->num_columns; i++) { 82 struct column_data *c = table->columns[i]; 83 84 for (j = 0; j < c->num_rows; j++) 85 free (c->rows[j].data); 86 free (c->header); 87 free (c->prefix); 88 free (c); 89 } 90 free (table->column_prefix); 91 free (table->columns); 92} 93 94int 95rtbl_add_column (rtbl_t table, const char *header, unsigned int flags) 96{ 97 struct column_data *col, **tmp; 98 99 tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp)); 100 if (tmp == NULL) 101 return ENOMEM; 102 table->columns = tmp; 103 col = malloc (sizeof (*col)); 104 if (col == NULL) 105 return ENOMEM; 106 col->header = strdup (header); 107 if (col->header == NULL) { 108 free (col); 109 return ENOMEM; 110 } 111 col->prefix = NULL; 112 col->width = 0; 113 col->flags = flags; 114 col->num_rows = 0; 115 col->rows = NULL; 116 table->columns[table->num_columns++] = col; 117 return 0; 118} 119 120static void 121column_compute_width (struct column_data *column) 122{ 123 int i; 124 125 column->width = strlen (column->header); 126 for (i = 0; i < column->num_rows; i++) 127 column->width = max (column->width, strlen (column->rows[i].data)); 128} 129 130int 131rtbl_set_prefix (rtbl_t table, const char *prefix) 132{ 133 if (table->column_prefix) 134 free (table->column_prefix); 135 table->column_prefix = strdup (prefix); 136 if (table->column_prefix == NULL) 137 return ENOMEM; 138 return 0; 139} 140 141int 142rtbl_set_column_prefix (rtbl_t table, const char *column, 143 const char *prefix) 144{ 145 struct column_data *c = rtbl_get_column (table, column); 146 147 if (c == NULL) 148 return -1; 149 if (c->prefix) 150 free (c->prefix); 151 c->prefix = strdup (prefix); 152 if (c->prefix == NULL) 153 return ENOMEM; 154 return 0; 155} 156 157 158static const char * 159get_column_prefix (rtbl_t table, struct column_data *c) 160{ 161 if (c == NULL) 162 return ""; 163 if (c->prefix) 164 return c->prefix; 165 if (table->column_prefix) 166 return table->column_prefix; 167 return ""; 168} 169 170int 171rtbl_add_column_entry (rtbl_t table, const char *column, const char *data) 172{ 173 struct column_entry row, *tmp; 174 175 struct column_data *c = rtbl_get_column (table, column); 176 177 if (c == NULL) 178 return -1; 179 180 row.data = strdup (data); 181 if (row.data == NULL) 182 return ENOMEM; 183 tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp)); 184 if (tmp == NULL) { 185 free (row.data); 186 return ENOMEM; 187 } 188 c->rows = tmp; 189 c->rows[c->num_rows++] = row; 190 return 0; 191} 192 193int 194rtbl_format (rtbl_t table, FILE * f) 195{ 196 int i, j; 197 198 for (i = 0; i < table->num_columns; i++) 199 column_compute_width (table->columns[i]); 200 for (i = 0; i < table->num_columns; i++) { 201 struct column_data *c = table->columns[i]; 202 203 fprintf (f, "%s", get_column_prefix (table, c)); 204 fprintf (f, "%-*s", (int)c->width, c->header); 205 } 206 fprintf (f, "\n"); 207 208 for (j = 0;; j++) { 209 int flag = 0; 210 211 for (i = 0; flag == 0 && i < table->num_columns; ++i) { 212 struct column_data *c = table->columns[i]; 213 214 if (c->num_rows > j) { 215 ++flag; 216 break; 217 } 218 } 219 if (flag == 0) 220 break; 221 222 for (i = 0; i < table->num_columns; i++) { 223 int w; 224 struct column_data *c = table->columns[i]; 225 226 w = c->width; 227 228 if ((c->flags & RTBL_ALIGN_RIGHT) == 0) 229 w = -w; 230 fprintf (f, "%s", get_column_prefix (table, c)); 231 if (c->num_rows <= j) 232 fprintf (f, "%*s", w, ""); 233 else 234 fprintf (f, "%*s", w, c->rows[j].data); 235 } 236 fprintf (f, "\n"); 237 } 238 return 0; 239} 240 241#ifdef TEST 242int 243main (int argc, char **argv) 244{ 245 rtbl_t table; 246 unsigned int a, b, c, d; 247 248 table = rtbl_create (); 249 rtbl_add_column (table, "Issued", 0, &a); 250 rtbl_add_column (table, "Expires", 0, &b); 251 rtbl_add_column (table, "Foo", RTBL_ALIGN_RIGHT, &d); 252 rtbl_add_column (table, "Principal", 0, &c); 253 254 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 255 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 256 rtbl_add_column_entry (table, d, "73"); 257 rtbl_add_column_entry (table, d, "0"); 258 rtbl_add_column_entry (table, d, "-2000"); 259 rtbl_add_column_entry (table, c, "krbtgt/NADA.KTH.SE@NADA.KTH.SE"); 260 261 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 262 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 263 rtbl_add_column_entry (table, c, "afs/pdc.kth.se@NADA.KTH.SE"); 264 265 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 266 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 267 rtbl_add_column_entry (table, c, "afs@NADA.KTH.SE"); 268 269 rtbl_set_prefix (table, " "); 270 rtbl_set_column_prefix (table, a, ""); 271 272 rtbl_format (table, stdout); 273 274 rtbl_destroy (table); 275 276} 277 278#endif 279