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> 36 RCSID ("$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 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->header); 87 free (c->prefix); 88 free (c); 89 } 90 free (table->column_prefix); 91 free (table->columns); 92 } 93 94 int 95 rtbl_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 120 static void 121 column_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 130 int 131 rtbl_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 141 int 142 rtbl_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 158 static const char * 159 get_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 170 int 171 rtbl_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 193 int 194 rtbl_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 242 int 243 main (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