1 /* 2 * Copyright (c) 2000, 2002 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> 36 RCSID ("$Id: rtbl.c,v 1.4 2002/09/04 21:25:09 joda Exp $"); 37 #endif 38 #include "roken.h" 39 #include "rtbl.h" 40 41 struct column_entry { 42 char *data; 43 }; 44 45 struct 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 54 struct rtbl_data { 55 char *column_prefix; 56 size_t num_columns; 57 struct column_data **columns; 58 }; 59 60 rtbl_t 61 rtbl_create (void) 62 { 63 return calloc (1, sizeof (struct rtbl_data)); 64 } 65 66 static struct column_data * 67 rtbl_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 76 void 77 rtbl_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->rows); 87 free (c->header); 88 free (c->prefix); 89 free (c); 90 } 91 free (table->column_prefix); 92 free (table->columns); 93 free (table); 94 } 95 96 int 97 rtbl_add_column (rtbl_t table, const char *header, unsigned int flags) 98 { 99 struct column_data *col, **tmp; 100 101 tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp)); 102 if (tmp == NULL) 103 return ENOMEM; 104 table->columns = tmp; 105 col = malloc (sizeof (*col)); 106 if (col == NULL) 107 return ENOMEM; 108 col->header = strdup (header); 109 if (col->header == NULL) { 110 free (col); 111 return ENOMEM; 112 } 113 col->prefix = NULL; 114 col->width = 0; 115 col->flags = flags; 116 col->num_rows = 0; 117 col->rows = NULL; 118 table->columns[table->num_columns++] = col; 119 return 0; 120 } 121 122 static void 123 column_compute_width (struct column_data *column) 124 { 125 int i; 126 127 column->width = strlen (column->header); 128 for (i = 0; i < column->num_rows; i++) 129 column->width = max (column->width, strlen (column->rows[i].data)); 130 } 131 132 int 133 rtbl_set_prefix (rtbl_t table, const char *prefix) 134 { 135 if (table->column_prefix) 136 free (table->column_prefix); 137 table->column_prefix = strdup (prefix); 138 if (table->column_prefix == NULL) 139 return ENOMEM; 140 return 0; 141 } 142 143 int 144 rtbl_set_column_prefix (rtbl_t table, const char *column, 145 const char *prefix) 146 { 147 struct column_data *c = rtbl_get_column (table, column); 148 149 if (c == NULL) 150 return -1; 151 if (c->prefix) 152 free (c->prefix); 153 c->prefix = strdup (prefix); 154 if (c->prefix == NULL) 155 return ENOMEM; 156 return 0; 157 } 158 159 160 static const char * 161 get_column_prefix (rtbl_t table, struct column_data *c) 162 { 163 if (c == NULL) 164 return ""; 165 if (c->prefix) 166 return c->prefix; 167 if (table->column_prefix) 168 return table->column_prefix; 169 return ""; 170 } 171 172 int 173 rtbl_add_column_entry (rtbl_t table, const char *column, const char *data) 174 { 175 struct column_entry row, *tmp; 176 177 struct column_data *c = rtbl_get_column (table, column); 178 179 if (c == NULL) 180 return -1; 181 182 row.data = strdup (data); 183 if (row.data == NULL) 184 return ENOMEM; 185 tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp)); 186 if (tmp == NULL) { 187 free (row.data); 188 return ENOMEM; 189 } 190 c->rows = tmp; 191 c->rows[c->num_rows++] = row; 192 return 0; 193 } 194 195 int 196 rtbl_format (rtbl_t table, FILE * f) 197 { 198 int i, j; 199 200 for (i = 0; i < table->num_columns; i++) 201 column_compute_width (table->columns[i]); 202 for (i = 0; i < table->num_columns; i++) { 203 struct column_data *c = table->columns[i]; 204 205 fprintf (f, "%s", get_column_prefix (table, c)); 206 fprintf (f, "%-*s", (int)c->width, c->header); 207 } 208 fprintf (f, "\n"); 209 210 for (j = 0;; j++) { 211 int flag = 0; 212 213 for (i = 0; flag == 0 && i < table->num_columns; ++i) { 214 struct column_data *c = table->columns[i]; 215 216 if (c->num_rows > j) { 217 ++flag; 218 break; 219 } 220 } 221 if (flag == 0) 222 break; 223 224 for (i = 0; i < table->num_columns; i++) { 225 int w; 226 struct column_data *c = table->columns[i]; 227 228 w = c->width; 229 230 if ((c->flags & RTBL_ALIGN_RIGHT) == 0) 231 w = -w; 232 fprintf (f, "%s", get_column_prefix (table, c)); 233 if (c->num_rows <= j) 234 fprintf (f, "%*s", w, ""); 235 else 236 fprintf (f, "%*s", w, c->rows[j].data); 237 } 238 fprintf (f, "\n"); 239 } 240 return 0; 241 } 242 243 #ifdef TEST 244 int 245 main (int argc, char **argv) 246 { 247 rtbl_t table; 248 unsigned int a, b, c, d; 249 250 table = rtbl_create (); 251 rtbl_add_column (table, "Issued", 0, &a); 252 rtbl_add_column (table, "Expires", 0, &b); 253 rtbl_add_column (table, "Foo", RTBL_ALIGN_RIGHT, &d); 254 rtbl_add_column (table, "Principal", 0, &c); 255 256 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 257 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 258 rtbl_add_column_entry (table, d, "73"); 259 rtbl_add_column_entry (table, d, "0"); 260 rtbl_add_column_entry (table, d, "-2000"); 261 rtbl_add_column_entry (table, c, "krbtgt/NADA.KTH.SE@NADA.KTH.SE"); 262 263 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 264 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 265 rtbl_add_column_entry (table, c, "afs/pdc.kth.se@NADA.KTH.SE"); 266 267 rtbl_add_column_entry (table, a, "Jul 7 21:19:29"); 268 rtbl_add_column_entry (table, b, "Jul 8 07:19:29"); 269 rtbl_add_column_entry (table, c, "afs@NADA.KTH.SE"); 270 271 rtbl_set_prefix (table, " "); 272 rtbl_set_column_prefix (table, a, ""); 273 274 rtbl_format (table, stdout); 275 276 rtbl_destroy (table); 277 278 } 279 280 #endif 281