Bump up version to 0.2
[k3conf/k3conf.git] / common / autoadjust_table.c
1 /*
2  * Table printing Libraries
3  *
4  * Copyright (C) 2010-2019 Texas Instruments Incorporated - https://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)
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;
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)
308         return autoadjust_table_generic_fprint(stream, table, row_nbr, col_nbr,
309                                                TABLE_HAS_SUBTITLE);
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)
340         return autoadjust_table_fprint(stdout, table, row_nbr, col_nbr);
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])
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;
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])
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;