1 /*
2 * Table printing Libraries
3 *
4 * Copyright (C) 2010-2019 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution.
18 *
19 * Neither the name of Texas Instruments Incorporated nor the names of
20 * its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
37 #include <autoadjust_table.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
43 /* #define AUTOADJUST_TABLE_DEBUG */
44 #ifdef AUTOADJUST_TABLE_DEBUG
45 #define dprintf(format, ...) printf(format, ## __VA_ARGS__)
46 #else
47 #define dprintf(format, ...)
48 #endif
51 /* ------------------------------------------------------------------------*//**
52 * @FUNCTION autoadjust_table_generic_fprint
53 * @BRIEF print elements into a table which size automatically
54 * adjusts.
55 * @RETURNS 0 in case of success
56 * -1 in case of incorrect pointer
57 * -2 in case of memory allocation error
58 * -3 one element of the table is longer than
59 * TABLE_MAX_ELT_LEN
60 * @param[in,out] stream: output file
61 * @param[in] table: elements to be printed
62 * format: table[row][col][string]
63 * @param[in] row_nbr: number of rows
64 * @param[in] col_nbr: number of columns
65 * @param[in] flags: table format flags
66 * @DESCRIPTION print elements into a table which size automatically
67 * adjusts. The printed table depends on the format flags:
68 *
69 * TABLE_HAS_TITLE:
70 *
71 * |------------------------------------------------------------------|
72 * | elements[0][0] |
73 * |------------------------------------------------------------------|
74 * | elements[1][0] | elements[1][1] | elements[1][col-1] |
75 * | elements[2][0] | elements[2][1] | elements[2][col-1] |
76 * | elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
77 * |------------------------------------------------------------------|
78 *
79 * TABLE_HAS_SUBTITLE:
80 *
81 * |------------------------------------------------------------------|
82 * | elements[0][0] | elements[0][1] | elements[0][col-1] |
83 * |------------------------------------------------------------------|
84 * | elements[1][0] | elements[1][1] | elements[1][col-1] |
85 * | elements[2][0] | elements[2][1] | elements[2][col-1] |
86 * | elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
87 * |------------------------------------------------------------------|
88 *
89 * TABLE_HAS_TITLE | TABLE_HAS_SUBTITLE:
90 *
91 * |------------------------------------------------------------------|
92 * | elements[0][0] |
93 * |------------------------------------------------------------------|
94 * | elements[1][0] | elements[1][1] | elements[1][col-1] |
95 * |------------------------------------------------------------------|
96 * | elements[2][0] | elements[2][1] | elements[2][col-1] |
97 * | elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
98 * |------------------------------------------------------------------|
99 *//*------------------------------------------------------------------------ */
100 int autoadjust_table_generic_fprint(FILE *stream,
101 char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN],
102 unsigned int row_nbr, unsigned int col_nbr, unsigned int flags)
103 {
104 int has_title = !!(flags & TABLE_HAS_TITLE);
105 unsigned int max_elt_size[TABLE_MAX_COL];
106 unsigned int total_dash_nbr = 0;
107 unsigned int total_width = 0;
108 char *dash_line = NULL;
109 unsigned int col, row;
110 unsigned int strln;
111 char *title = NULL;
112 char *line = NULL;
113 unsigned int tmp;
115 if (stream == NULL) {
116 printf("autoadjust_table_fprint() error: stream == NULL!\n");
117 return -1;
118 }
119 if (table == NULL) {
120 printf("autoadjust_table_fprint() error: table == NULL!\n");
121 return -1;
122 }
123 if (row_nbr > TABLE_MAX_ROW) {
124 printf("autoadjust_table_fprint() error: row_nbr (%d) > "
125 "TABLE_MAX_ROW (%d)!\n", row_nbr, TABLE_MAX_ROW);
126 return -1;
127 }
128 if (col_nbr > TABLE_MAX_COL) {
129 printf("autoadjust_table_fprint() error: col_nbr (%d) > "
130 "TABLE_MAX_COL (%d)!\n", col_nbr, TABLE_MAX_COL);
131 return -1;
132 }
134 if (has_title)
135 title = table[0][0];
137 #ifdef AUTOADJUST_TABLE_DEBUG
138 dprintf("row_nbr = %d, col_nbr = %d\n", row_nbr, col_nbr);
139 for (row = 0; row < row_nbr; row++) {
140 for (col = 0; col < col_nbr; col++)
141 dprintf("element[%d][%d] = %s\n",
142 row, col, table[row][col]);
143 }
144 #endif
147 /* compute width of each column of the table */
148 for (col = 0; col < col_nbr; col++)
149 max_elt_size[col] = 0;
151 /* title length will be added to total width later */
152 row = has_title ? 1 : 0;
154 for (; row < row_nbr; row++) {
155 tmp = 0;
156 /* Get total length of strings in this line */
157 for (col = 0; col < col_nbr; col++) {
158 strln = strlen(table[row][col]);
159 if (strln > TABLE_MAX_ELT_LEN) {
160 printf("%s(): WARNING: \"%s\" size (%u) > "
161 "TABLE_MAX_ELT_LEN (%u)!\n",
162 __func__, table[row][col],
163 strln, TABLE_MAX_ELT_LEN);
164 strln = TABLE_MAX_ELT_LEN;
165 }
167 if (strln > max_elt_size[col]) {
168 max_elt_size[col] = strln;
169 dprintf("new max_elt_size[%d] = %d\n",
170 col, max_elt_size[col]);
171 }
172 }
173 }
175 /* Compute the total width of the table, and allocate memory for it */
176 for (col = 0; col < col_nbr; col++)
177 total_width += max_elt_size[col];
178 /* Add number of '|' separators per line */
179 total_width += (col_nbr + 1);
180 /* Add number of space character separators (2 per element) */
181 total_width += col_nbr * 2;
183 /* Compensate if the title is longer than table width */
184 if (has_title) {
185 unsigned int avail;
187 strln = strlen(title);
188 avail = total_width - 4; /* exclude left and right borders */
189 dprintf("title_width=%d\n", strln);
191 if (avail < strln) {
192 /* Number of chars to compensate per column */
193 tmp = (strln - avail + col_nbr - 1) / col_nbr;
195 total_width = 0;
196 for (col = 0; col < col_nbr; col++) {
197 max_elt_size[col] += tmp;
198 total_width += max_elt_size[col];
199 dprintf("new max_elt_size[%d] = %d\n",
200 col, max_elt_size[col]);
201 }
202 /* Add number of separators per line */
203 total_width += (col_nbr + 1);
204 total_width += col_nbr * 2;
205 }
206 }
208 dprintf("total_width = %d\n", total_width);
209 line = malloc(sizeof(char) * (total_width + 1));
210 if (line == NULL) {
211 printf("autoadjust_table_fprint(): line malloc error!\n");
212 return -2;
213 }
214 line[0] = '\0';
215 line[total_width] = '\0';
217 /*
218 * Compute the total number of dash characters,
219 * used to delimit the table, and allocate memory for it
220 */
221 total_dash_nbr = total_width - 2;
222 dash_line = malloc(sizeof(char) * (total_width + 1));
223 dprintf("total_dash_nbr = %d\n", total_dash_nbr);
224 if (dash_line == NULL) {
225 printf("autoadjust_table_fprint(): dash_line malloc error!\n");
226 return -2;
227 }
228 dash_line[0] = '\0';
229 dash_line[total_width] = '\0';
231 dprintf("total_dash_nbr=%d\n", total_dash_nbr);
232 dprintf("total_width=%d\n", total_width);
234 /* Print table */
235 dash_line[0] = '|';
236 memset(dash_line + sizeof(char), '-', total_dash_nbr);
237 dash_line[total_dash_nbr + 1] = '|';
238 fprintf(stream, "%s\n", dash_line);
240 row = 0;
241 if (has_title) {
242 strcpy(line, "| ");
243 strcat(line, title);
244 tmp = total_width - 4 - strlen(title);
245 while (tmp--)
246 strcat(line, " ");
248 strcat(line, " |");
249 fprintf(stream, "%s\n", line);
250 fprintf(stream, "%s\n", dash_line);
251 row++;
252 }
254 for (; row < row_nbr; row++) {
255 strcpy(line, "|");
256 for (col = 0; col < col_nbr; col++) {
257 strcat(line, " ");
258 strncat(line, table[row][col], TABLE_MAX_ELT_LEN);
259 if (strlen(table[row][col]) != TABLE_MAX_ELT_LEN) {
260 for (tmp = strlen(table[row][col]);
261 tmp < max_elt_size[col]; tmp++)
262 strcat(line, " ");
263 }
264 strcat(line, " |");
265 }
266 fprintf(stream, "%s\n", line);
267 if (flags & TABLE_HAS_SUBTITLE) {
268 fprintf(stream, "%s\n", dash_line);
269 flags &= ~TABLE_HAS_SUBTITLE;
270 }
271 }
272 fprintf(stream, "%s\n\n", dash_line);
274 free(dash_line);
275 free(line);
277 return 0;
278 }
280 /* ------------------------------------------------------------------------*//**
281 * @FUNCTION autoadjust_table_fprint
282 * @BRIEF print elements into a table which size automatically
283 * adjusts.
284 * @RETURNS 0 in case of success
285 * -1 in case of incorrect pointer
286 * -2 in case of memory allocation error
287 * -3 one element of the table is longer than
288 * TABLE_MAX_ELT_LEN
289 * @param[in,out] stream: output file
290 * @param[in] table: elements to be printed
291 * format: table[row][col][string]
292 * @param[in] row_nbr: number of rows
293 * @param[in] col_nbr: number of columns
294 * @DESCRIPTION print elements into a table which size automatically
295 * adjusts. The printed table looks like this:
296 * |------------------------------------------------------------------|
297 * | elements[0][0] | elements[0][1] | elements[0][col-1] |
298 * |------------------------------------------------------------------|
299 * | elements[1][0] | elements[1][1] | elements[1][col-1] |
300 * | elements[2][0] | elements[2][1] | elements[2][col-1] |
301 * | elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
302 * |------------------------------------------------------------------|
303 *//*------------------------------------------------------------------------ */
304 int autoadjust_table_fprint(FILE *stream,
305 char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN],
306 unsigned int row_nbr, unsigned int col_nbr)
307 {
308 return autoadjust_table_generic_fprint(stream, table, row_nbr, col_nbr,
309 TABLE_HAS_SUBTITLE);
310 }
313 /* ------------------------------------------------------------------------*//**
314 * @FUNCTION autoadjust_table_print
315 * @BRIEF print to console elements into a table which size
316 * automatically adjusts.
317 * @RETURNS 0 in case of success
318 * -1 in case of incorrect pointer
319 * -2 in case of memory allocation error
320 * -3 one element of the table is longer than
321 * TABLE_MAX_ELT_LEN
322 * @param[in] table: elements to be printed
323 * format: table[row][col][string]
324 * @param[in] row_nbr: number of rows
325 * @param[in] col_nbr: number of columns
326 * @DESCRIPTION print to console elements into a table which size
327 * automatically adjusts. The printed table is like this:
328 * |------------------------------------------------------------------|
329 * | elements[0][0] | elements[0][1] | elements[0][col-1] |
330 * |------------------------------------------------------------------|
331 * | elements[1][0] | elements[1][1] | elements[1][col-1] |
332 * | elements[2][0] | elements[2][1] | elements[2][col-1] |
333 * | elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
334 * |------------------------------------------------------------------|
335 *//*------------------------------------------------------------------------ */
336 int autoadjust_table_print(
337 char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN],
338 unsigned int row_nbr, unsigned int col_nbr)
339 {
340 return autoadjust_table_fprint(stdout, table, row_nbr, col_nbr);
341 }
344 /* ------------------------------------------------------------------------*//**
345 * @FUNCTION autoadjust_table_strncpy
346 * @BRIEF copy string into table element, making sure it can fit.
347 * @RETURNS 0 in case of success
348 * -1 in case of incorrect argument(s)
349 * -3 one element of the table longer than
350 * TABLE_MAX_ELT_LEN
351 * @param[in,out] table: elements to be printed
352 * format: table[row][col][string]
353 * @param[in] row: number of rows
354 * @param[in] col: number of columns
355 * @param[in] s: string to copy
356 * @DESCRIPTION copy string into table element, making sure it can fit.
357 *//*------------------------------------------------------------------------ */
358 int autoadjust_table_strncpy(
359 char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN],
360 unsigned int row, unsigned int col, char s[TABLE_MAX_ELT_LEN])
361 {
362 if (table == NULL) {
363 fprintf(stderr, "%s(): table == NULL!!!\n", __func__);
364 return -1;
365 }
366 if (s == NULL) {
367 fprintf(stderr, "%s(): s == NULL!!!\n", __func__);
368 return -1;
369 }
370 if (row >= TABLE_MAX_ROW) {
371 fprintf(stderr, "%s(): row (%u) >= TABLE_MAX_ROW (%u)\n",
372 __func__, row, TABLE_MAX_ROW);
373 return -1;
374 }
375 if (col >= TABLE_MAX_COL) {
376 fprintf(stderr, "%s(): col (%u) >= TABLE_MAX_COL (%u)\n",
377 __func__, col, TABLE_MAX_COL);
378 return -1;
379 }
380 if (strlen(s) >= TABLE_MAX_ELT_LEN) {
381 fprintf(stderr, "%s(): "
382 "strlen(%s)=%lu >= TABLE_MAX_ELT_LEN (%u)!\n", __func__,
383 s, strlen(s), TABLE_MAX_ELT_LEN);
384 return -3;
385 }
387 strncpy(table[row][col], s, TABLE_MAX_ELT_LEN);
389 return 0;
390 }
393 /* ------------------------------------------------------------------------*//**
394 * @FUNCTION autoadjust_table_init
395 * @BRIEF fill table with empty strings
396 * @RETURNS 0 in case of success
397 * -1 in case of incorrect pointer
398 * @param[in,out] table: table to fill with empty strings
399 * @DESCRIPTION fill table with empty strings, so that user does not
400 * need to fill empty cell(s).
401 *//*------------------------------------------------------------------------ */
402 int autoadjust_table_init(
403 char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN])
404 {
405 unsigned int col, row;
407 if (table == NULL) {
408 printf("autoadjust_table_init() error: table == NULL!\n");
409 return -1;
410 }
412 for (row = 0; row < TABLE_MAX_ROW; row++)
413 for (col = 0; col < TABLE_MAX_COL; col++)
414 table[row][col][0] = '\0';
416 return 0;
417 }