ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/table.C
Revision: 1.1
Committed: Thu Jul 19 08:24:59 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * table.C: Table rendering class.
3     * Rights to this code are documented in doc/LICENSE.
4     *
5     * NOTE: This is a work in progress and will probably change considerably
6     * later on.
7     *
8     * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
9     */
10    
11     static char const rcsid[] = "$Id";
12    
13     #include "atheme.h"
14    
15     static void
16     table_destroy (void *obj)
17     {
18     table_t *table = (table_t *) obj;
19     node_t *n, *tn;
20    
21     return_if_fail (table != NULL);
22    
23     LIST_FOREACH_SAFE (n, tn, table->rows.head)
24     {
25     table_row_t *r = (table_row_t *) n->data;
26     node_t *n2, *tn2;
27    
28     return_if_fail (r != NULL);
29    
30     LIST_FOREACH_SAFE (n2, tn2, r->cells.head)
31     {
32     table_cell_t *c = (table_cell_t *) n2->data;
33    
34     free (c->name);
35     free (c->value);
36     free (c);
37     node_del (n2, &r->cells);
38     node_free (n2);
39     }
40    
41     free (r);
42    
43     node_del (n, &table->rows);
44     node_free (n);
45     }
46    
47     free (table);
48     }
49    
50     /*
51     * table_new(const char *fmt, ...)
52     *
53     * Table constructor.
54     *
55     * Inputs:
56     * - printf-style string to name the table with.
57     *
58     * Outputs:
59     * - a table object.
60     *
61     * Side Effects:
62     * - none
63     */
64     table_t *
65     table_new (const char *fmt, ...)
66     {
67     va_list vl;
68     char *buf;
69     table_t *out;
70    
71     return_val_if_fail (fmt != NULL, NULL);
72    
73     va_start (vl, fmt);
74     vasprintf (&buf, fmt, vl);
75     va_end (vl);
76    
77     out = static_cast<table_t *> (scalloc (sizeof (table_t), 1));
78     object_init (&out->parent, buf, table_destroy);
79     free (buf);
80    
81     return out;
82     }
83    
84     /*
85     * table_row_new
86     *
87     * Creates a table row. This isn't an object.
88     *
89     * Inputs:
90     * - table to associate to.
91     *
92     * Outputs:
93     * - a table row
94     *
95     * Side Effects:
96     * - none
97     */
98     table_row_t *
99     table_row_new (table_t * t)
100     {
101     table_row_t *out;
102    
103     return_val_if_fail (t != NULL, NULL);
104    
105     out = static_cast<table_row_t *> (scalloc (sizeof (table_row_t), 1));
106    
107     node_add (out, node_create (), &t->rows);
108    
109     return out;
110     }
111    
112     /*
113     * table_cell_associate
114     *
115     * Associates a cell with a row.
116     *
117     * Inputs:
118     * - row to add cell to.
119     *
120     * Outputs:
121     * - nothing
122     *
123     * Side Effects:
124     * - none
125     */
126     void
127     table_cell_associate (table_row_t * r, const char *name, const char *value)
128     {
129     table_cell_t *c;
130    
131     return_if_fail (r != NULL);
132     return_if_fail (name != NULL);
133     return_if_fail (value != NULL);
134    
135     c = static_cast<table_cell_t *> (scalloc (sizeof (table_cell_t), 1));
136    
137     c->name = sstrdup (name);
138     c->value = sstrdup (value);
139    
140     node_add (c, node_create (), &r->cells);
141     }
142    
143     /*
144     * table_render
145     *
146     * Renders a table. This is a two-pass operation, the first one to find out
147     * the width of each cell, and then the second to render the data.
148     *
149     * Inputs:
150     * - a table
151     * - a callback function
152     * - opaque data
153     *
154     * Outputs:
155     * - none
156     *
157     * Side Effects:
158     * - a callback function is called for each row of the table.
159     */
160     void
161     table_render (table_t * t, void (*callback) (const char *line, void *data), void *data)
162     {
163     node_t *n;
164     table_row_t *f;
165     size_t bufsz = 0;
166     char *buf = NULL;
167     char *p;
168     int i;
169    
170     return_if_fail (t != NULL);
171     return_if_fail (callback != NULL);
172    
173     f = (table_row_t *) t->rows.head->data;
174    
175     LIST_FOREACH (n, t->rows.head)
176     {
177     table_row_t *r = (table_row_t *) n->data;
178     node_t *n2, *rn;
179    
180     /* we, uhh... we don't provide a macro for dealing with two lists at once ;) */
181     for (n2 = r->cells.head, rn = f->cells.head; n2 != NULL && rn != NULL; n2 = n2->next, rn = rn->next)
182     {
183     table_cell_t *c, *rc;
184     size_t sz;
185    
186     c = (table_cell_t *) n2->data;
187     rc = (table_cell_t *) rn->data;
188    
189     if ((sz = strlen (c->name)) > (size_t) rc->width)
190     rc->width = sz;
191    
192     if ((sz = strlen (c->value)) > (size_t) rc->width)
193     rc->width = sz;
194     }
195     }
196    
197     /* now total up the result. */
198     LIST_FOREACH (n, f->cells.head)
199     {
200     table_cell_t *c = (table_cell_t *) n->data;
201     bufsz += c->width + 1;
202     }
203    
204     buf = static_cast<char *> (smalloc (bufsz));
205     *buf = '\0';
206    
207     /* start outputting the header. */
208     callback (asobject (t)->name, data);
209     LIST_FOREACH (n, f->cells.head)
210     {
211     table_cell_t *c = (table_cell_t *) n->data;
212     char fmtbuf[12];
213     char buf2[1024];
214    
215     /* dynamically generate the format string based on width. */
216     snprintf (fmtbuf, 12, n->next != NULL ? "%%-%ds " : "%%s", c->width);
217     snprintf (buf2, 1024, fmtbuf, c->name);
218    
219     strlcat (buf, buf2, bufsz);
220     }
221     callback (buf, data);
222     *buf = '\0';
223    
224     /* separator line */
225     p = buf;
226     LIST_FOREACH (n, f->cells.head)
227     {
228     table_cell_t *c = (table_cell_t *) n->data;
229    
230     if (n->next != NULL)
231     {
232     for (i = 0; i < c->width; i++)
233     *p++ = '-';
234     *p++ = ' ';
235     }
236     else
237     for (i = 0; i < (int) strlen (c->name); i++)
238     *p++ = '-';
239     }
240     *p = '\0';
241     callback (buf, data);
242     *buf = '\0';
243    
244     LIST_FOREACH (n, t->rows.head)
245     {
246     table_row_t *r = (table_row_t *) n->data;
247     node_t *n2, *rn;
248    
249     for (n2 = r->cells.head, rn = f->cells.head; n2 != NULL && rn != NULL; n2 = n2->next, rn = rn->next)
250     {
251     table_cell_t *c, *rc;
252     char fmtbuf[12];
253     char buf2[1024];
254    
255     c = (table_cell_t *) n2->data;
256     rc = (table_cell_t *) rn->data;
257    
258     /* dynamically generate the format string based on width. */
259     snprintf (fmtbuf, 12, n2->next != NULL ? "%%-%ds " : "%%s", rc->width);
260     snprintf (buf2, 1024, fmtbuf, c->value);
261    
262     strlcat (buf, buf2, bufsz);
263     }
264     callback (buf, data);
265     *buf = '\0';
266     }
267    
268     /* separator line */
269     p = buf;
270     LIST_FOREACH (n, f->cells.head)
271     {
272     table_cell_t *c = (table_cell_t *) n->data;
273    
274     if (n->next != NULL)
275     {
276     for (i = 0; i < c->width; i++)
277     *p++ = '-';
278     *p++ = ' ';
279     }
280     else
281     for (i = 0; i < (int) strlen (c->name); i++)
282     *p++ = '-';
283     }
284     *p = '\0';
285     callback (buf, data);
286     *buf = '\0';
287     }
288    
289     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
290     * vim:ts=8
291     * vim:sw=8
292     * vim:noexpandtab
293     */