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

# Content
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 */