~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/roken/rtbl.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000, 2002, 2004 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$");
 
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
    unsigned int column_id;
 
53
    char *suffix;
 
54
};
 
55
 
 
56
struct rtbl_data {
 
57
    char *column_prefix;
 
58
    size_t num_columns;
 
59
    struct column_data **columns;
 
60
    unsigned int flags;
 
61
    char *column_separator;
 
62
};
 
63
 
 
64
rtbl_t ROKEN_LIB_FUNCTION
 
65
rtbl_create (void)
 
66
{
 
67
    return calloc (1, sizeof (struct rtbl_data));
 
68
}
 
69
 
 
70
void ROKEN_LIB_FUNCTION
 
71
rtbl_set_flags (rtbl_t table, unsigned int flags)
 
72
{
 
73
    table->flags = flags;
 
74
}
 
75
 
 
76
unsigned int ROKEN_LIB_FUNCTION
 
77
rtbl_get_flags (rtbl_t table)
 
78
{
 
79
    return table->flags;
 
80
}
 
81
 
 
82
static struct column_data *
 
83
rtbl_get_column_by_id (rtbl_t table, unsigned int id)
 
84
{
 
85
    int i;
 
86
    for(i = 0; i < table->num_columns; i++)
 
87
        if(table->columns[i]->column_id == id)
 
88
            return table->columns[i];
 
89
    return NULL;
 
90
}
 
91
 
 
92
static struct column_data *
 
93
rtbl_get_column (rtbl_t table, const char *column)
 
94
{
 
95
    int i;
 
96
    for(i = 0; i < table->num_columns; i++)
 
97
        if(strcmp(table->columns[i]->header, column) == 0)
 
98
            return table->columns[i];
 
99
    return NULL;
 
100
}
 
101
 
 
102
void ROKEN_LIB_FUNCTION
 
103
rtbl_destroy (rtbl_t table)
 
104
{
 
105
    int i, j;
 
106
 
 
107
    for (i = 0; i < table->num_columns; i++) {
 
108
        struct column_data *c = table->columns[i];
 
109
 
 
110
        for (j = 0; j < c->num_rows; j++)
 
111
            free (c->rows[j].data);
 
112
        free (c->rows);
 
113
        free (c->header);
 
114
        free (c->prefix);
 
115
        free (c->suffix);
 
116
        free (c);
 
117
    }
 
118
    free (table->column_prefix);
 
119
    free (table->column_separator);
 
120
    free (table->columns);
 
121
    free (table);
 
122
}
 
123
 
 
124
int ROKEN_LIB_FUNCTION
 
125
rtbl_add_column_by_id (rtbl_t table, unsigned int id,
 
126
                       const char *header, unsigned int flags)
 
127
{
 
128
    struct column_data *col, **tmp;
 
129
 
 
130
    tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp));
 
131
    if (tmp == NULL)
 
132
        return ENOMEM;
 
133
    table->columns = tmp;
 
134
    col = malloc (sizeof (*col));
 
135
    if (col == NULL)
 
136
        return ENOMEM;
 
137
    col->header = strdup (header);
 
138
    if (col->header == NULL) {
 
139
        free (col);
 
140
        return ENOMEM;
 
141
    }
 
142
    col->prefix = NULL;
 
143
    col->width = 0;
 
144
    col->flags = flags;
 
145
    col->num_rows = 0;
 
146
    col->rows = NULL;
 
147
    col->column_id = id;
 
148
    col->suffix = NULL;
 
149
    table->columns[table->num_columns++] = col;
 
150
    return 0;
 
151
}
 
152
 
 
153
int ROKEN_LIB_FUNCTION
 
154
rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
 
155
{
 
156
    return rtbl_add_column_by_id(table, 0, header, flags);
 
157
}
 
158
 
 
159
int ROKEN_LIB_FUNCTION
 
160
rtbl_new_row(rtbl_t table)
 
161
{
 
162
    size_t max_rows = 0;
 
163
    size_t c;
 
164
    for (c = 0; c < table->num_columns; c++)
 
165
        if(table->columns[c]->num_rows > max_rows)
 
166
            max_rows = table->columns[c]->num_rows;
 
167
    for (c = 0; c < table->num_columns; c++) {
 
168
        struct column_entry *tmp;
 
169
 
 
170
        if(table->columns[c]->num_rows == max_rows)
 
171
            continue;
 
172
        tmp = realloc(table->columns[c]->rows,
 
173
                      max_rows * sizeof(table->columns[c]->rows));
 
174
        if(tmp == NULL)
 
175
            return ENOMEM;
 
176
        table->columns[c]->rows = tmp;
 
177
        while(table->columns[c]->num_rows < max_rows) {
 
178
            if((tmp[table->columns[c]->num_rows++].data = strdup("")) == NULL)
 
179
                return ENOMEM;
 
180
        }
 
181
    }
 
182
    return 0;
 
183
}
 
184
 
 
185
static void
 
186
column_compute_width (rtbl_t table, struct column_data *column)
 
187
{
 
188
    int i;
 
189
 
 
190
    if(table->flags & RTBL_HEADER_STYLE_NONE)
 
191
        column->width = 0;
 
192
    else
 
193
        column->width = strlen (column->header);
 
194
    for (i = 0; i < column->num_rows; i++)
 
195
        column->width = max (column->width, strlen (column->rows[i].data));
 
196
}
 
197
 
 
198
/* DEPRECATED */
 
199
int ROKEN_LIB_FUNCTION
 
200
rtbl_set_prefix (rtbl_t table, const char *prefix)
 
201
{
 
202
    if (table->column_prefix)
 
203
        free (table->column_prefix);
 
204
    table->column_prefix = strdup (prefix);
 
205
    if (table->column_prefix == NULL)
 
206
        return ENOMEM;
 
207
    return 0;
 
208
}
 
209
 
 
210
int ROKEN_LIB_FUNCTION
 
211
rtbl_set_separator (rtbl_t table, const char *separator)
 
212
{
 
213
    if (table->column_separator)
 
214
        free (table->column_separator);
 
215
    table->column_separator = strdup (separator);
 
216
    if (table->column_separator == NULL)
 
217
        return ENOMEM;
 
218
    return 0;
 
219
}
 
220
 
 
221
int ROKEN_LIB_FUNCTION
 
222
rtbl_set_column_prefix (rtbl_t table, const char *column,
 
223
                        const char *prefix)
 
224
{
 
225
    struct column_data *c = rtbl_get_column (table, column);
 
226
 
 
227
    if (c == NULL)
 
228
        return -1;
 
229
    if (c->prefix)
 
230
        free (c->prefix);
 
231
    c->prefix = strdup (prefix);
 
232
    if (c->prefix == NULL)
 
233
        return ENOMEM;
 
234
    return 0;
 
235
}
 
236
 
 
237
int ROKEN_LIB_FUNCTION
 
238
rtbl_set_column_affix_by_id(rtbl_t table, unsigned int id,
 
239
                            const char *prefix, const char *suffix)
 
240
{
 
241
    struct column_data *c = rtbl_get_column_by_id (table, id);
 
242
 
 
243
    if (c == NULL)
 
244
        return -1;
 
245
    if (c->prefix)
 
246
        free (c->prefix);
 
247
    if(prefix == NULL)
 
248
        c->prefix = NULL;
 
249
    else {
 
250
        c->prefix = strdup (prefix);
 
251
        if (c->prefix == NULL)
 
252
            return ENOMEM;
 
253
    }
 
254
 
 
255
    if (c->suffix)
 
256
        free (c->suffix);
 
257
    if(suffix == NULL)
 
258
        c->suffix = NULL;
 
259
    else {
 
260
        c->suffix = strdup (suffix);
 
261
        if (c->suffix == NULL)
 
262
            return ENOMEM;
 
263
    }
 
264
    return 0;
 
265
}
 
266
 
 
267
 
 
268
static const char *
 
269
get_column_prefix (rtbl_t table, struct column_data *c)
 
270
{
 
271
    if (c == NULL)
 
272
        return "";
 
273
    if (c->prefix)
 
274
        return c->prefix;
 
275
    if (table->column_prefix)
 
276
        return table->column_prefix;
 
277
    return "";
 
278
}
 
279
 
 
280
static const char *
 
281
get_column_suffix (rtbl_t table, struct column_data *c)
 
282
{
 
283
    if (c && c->suffix)
 
284
        return c->suffix;
 
285
    return "";
 
286
}
 
287
 
 
288
static int
 
289
add_column_entry (struct column_data *c, const char *data)
 
290
{
 
291
    struct column_entry row, *tmp;
 
292
 
 
293
    row.data = strdup (data);
 
294
    if (row.data == NULL)
 
295
        return ENOMEM;
 
296
    tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp));
 
297
    if (tmp == NULL) {
 
298
        free (row.data);
 
299
        return ENOMEM;
 
300
    }
 
301
    c->rows = tmp;
 
302
    c->rows[c->num_rows++] = row;
 
303
    return 0;
 
304
}
 
305
 
 
306
int ROKEN_LIB_FUNCTION
 
307
rtbl_add_column_entry_by_id (rtbl_t table, unsigned int id, const char *data)
 
308
{
 
309
    struct column_data *c = rtbl_get_column_by_id (table, id);
 
310
 
 
311
    if (c == NULL)
 
312
        return -1;
 
313
 
 
314
    return add_column_entry(c, data);
 
315
}
 
316
 
 
317
int ROKEN_LIB_FUNCTION
 
318
rtbl_add_column_entryv_by_id (rtbl_t table, unsigned int id,
 
319
                              const char *fmt, ...)
 
320
{
 
321
    va_list ap;
 
322
    char *str;
 
323
    int ret;
 
324
 
 
325
    va_start(ap, fmt);
 
326
    ret = vasprintf(&str, fmt, ap);
 
327
    va_end(ap);
 
328
    if (ret == -1)
 
329
        return -1;
 
330
    ret = rtbl_add_column_entry_by_id(table, id, str);
 
331
    free(str);
 
332
    return ret;
 
333
}
 
334
 
 
335
int ROKEN_LIB_FUNCTION
 
336
rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
 
337
{
 
338
    struct column_data *c = rtbl_get_column (table, column);
 
339
 
 
340
    if (c == NULL)
 
341
        return -1;
 
342
 
 
343
    return add_column_entry(c, data);
 
344
}
 
345
 
 
346
int ROKEN_LIB_FUNCTION
 
347
rtbl_add_column_entryv (rtbl_t table, const char *column, const char *fmt, ...)
 
348
{
 
349
    va_list ap;
 
350
    char *str;
 
351
    int ret;
 
352
 
 
353
    va_start(ap, fmt);
 
354
    ret = vasprintf(&str, fmt, ap);
 
355
    va_end(ap);
 
356
    if (ret == -1)
 
357
        return -1;
 
358
    ret = rtbl_add_column_entry(table, column, str);
 
359
    free(str);
 
360
    return ret;
 
361
}
 
362
 
 
363
 
 
364
int ROKEN_LIB_FUNCTION
 
365
rtbl_format (rtbl_t table, FILE * f)
 
366
{
 
367
    int i, j;
 
368
 
 
369
    for (i = 0; i < table->num_columns; i++)
 
370
        column_compute_width (table, table->columns[i]);
 
371
    if((table->flags & RTBL_HEADER_STYLE_NONE) == 0) {
 
372
        for (i = 0; i < table->num_columns; i++) {
 
373
            struct column_data *c = table->columns[i];
 
374
 
 
375
            if(table->column_separator != NULL && i > 0)
 
376
                fprintf (f, "%s", table->column_separator);
 
377
            fprintf (f, "%s", get_column_prefix (table, c));
 
378
            if(i == table->num_columns - 1 && c->suffix == NULL)
 
379
                /* last column, so no need to pad with spaces */
 
380
                fprintf (f, "%-*s", 0, c->header);
 
381
            else
 
382
                fprintf (f, "%-*s", (int)c->width, c->header);
 
383
            fprintf (f, "%s", get_column_suffix (table, c));
 
384
        }
 
385
        fprintf (f, "\n");
 
386
    }
 
387
 
 
388
    for (j = 0;; j++) {
 
389
        int flag = 0;
 
390
 
 
391
        /* are there any more rows left? */
 
392
        for (i = 0; flag == 0 && i < table->num_columns; ++i) {
 
393
            struct column_data *c = table->columns[i];
 
394
 
 
395
            if (c->num_rows > j) {
 
396
                ++flag;
 
397
                break;
 
398
            }
 
399
        }
 
400
        if (flag == 0)
 
401
            break;
 
402
 
 
403
        for (i = 0; i < table->num_columns; i++) {
 
404
            int w;
 
405
            struct column_data *c = table->columns[i];
 
406
 
 
407
            if(table->column_separator != NULL && i > 0)
 
408
                fprintf (f, "%s", table->column_separator);
 
409
 
 
410
            w = c->width;
 
411
 
 
412
            if ((c->flags & RTBL_ALIGN_RIGHT) == 0) {
 
413
                if(i == table->num_columns - 1 && c->suffix == NULL)
 
414
                    /* last column, so no need to pad with spaces */
 
415
                    w = 0;
 
416
                else
 
417
                    w = -w;
 
418
            }
 
419
            fprintf (f, "%s", get_column_prefix (table, c));
 
420
            if (c->num_rows <= j)
 
421
                fprintf (f, "%*s", w, "");
 
422
            else
 
423
                fprintf (f, "%*s", w, c->rows[j].data);
 
424
            fprintf (f, "%s", get_column_suffix (table, c));
 
425
        }
 
426
        fprintf (f, "\n");
 
427
    }
 
428
    return 0;
 
429
}
 
430
 
 
431
#ifdef TEST
 
432
int
 
433
main (int argc, char **argv)
 
434
{
 
435
    rtbl_t table;
 
436
 
 
437
    table = rtbl_create ();
 
438
    rtbl_add_column_by_id (table, 0, "Issued", 0);
 
439
    rtbl_add_column_by_id (table, 1, "Expires", 0);
 
440
    rtbl_add_column_by_id (table, 2, "Foo", RTBL_ALIGN_RIGHT);
 
441
    rtbl_add_column_by_id (table, 3, "Principal", 0);
 
442
 
 
443
    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
 
444
    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
 
445
    rtbl_add_column_entry_by_id (table, 2, "73");
 
446
    rtbl_add_column_entry_by_id (table, 2, "0");
 
447
    rtbl_add_column_entry_by_id (table, 2, "-2000");
 
448
    rtbl_add_column_entry_by_id (table, 3, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
 
449
 
 
450
    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
 
451
    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
 
452
    rtbl_add_column_entry_by_id (table, 3, "afs/pdc.kth.se@NADA.KTH.SE");
 
453
 
 
454
    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
 
455
    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
 
456
    rtbl_add_column_entry_by_id (table, 3, "afs@NADA.KTH.SE");
 
457
 
 
458
    rtbl_set_separator (table, "  ");
 
459
 
 
460
    rtbl_format (table, stdout);
 
461
 
 
462
    rtbl_destroy (table);
 
463
 
 
464
    printf("\n");
 
465
 
 
466
    table = rtbl_create ();
 
467
    rtbl_add_column_by_id (table, 0, "Column A", 0);
 
468
    rtbl_set_column_affix_by_id (table, 0, "<", ">");
 
469
    rtbl_add_column_by_id (table, 1, "Column B", 0);
 
470
    rtbl_set_column_affix_by_id (table, 1, "[", "]");
 
471
    rtbl_add_column_by_id (table, 2, "Column C", 0);
 
472
    rtbl_set_column_affix_by_id (table, 2, "(", ")");
 
473
 
 
474
    rtbl_add_column_entry_by_id (table, 0, "1");
 
475
    rtbl_new_row(table);
 
476
    rtbl_add_column_entry_by_id (table, 1, "2");
 
477
    rtbl_new_row(table);
 
478
    rtbl_add_column_entry_by_id (table, 2, "3");
 
479
    rtbl_new_row(table);
 
480
 
 
481
    rtbl_set_separator (table, "  ");
 
482
    rtbl_format (table, stdout);
 
483
 
 
484
    rtbl_destroy (table);
 
485
 
 
486
    return 0;
 
487
}
 
488
 
 
489
#endif