|
/* |
|
MIT License |
|
|
|
Copyright (c) 2023 Viacheslav Radko |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
of this software and associated documentation files (the "Software"), to deal |
|
in the Software without restriction, including without limitation the rights |
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
copies of the Software, and to permit persons to whom the Software is |
|
furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included in all |
|
copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
SOFTWARE. |
|
*/ |
|
|
|
/* |
|
# Table printer single header library |
|
|
|
This library should help to easily print tables in C and C++ like following: |
|
|
|
``` |
|
+--------+------+--------+------+ |
|
| N | | Square | | |
|
+--------+------+--------+------+ |
|
| 4 | even | 16 | even | |
|
+--------+------+--------+------+ |
|
| 5 | odd | | odd | |
|
+--------+------+--------+------+ |
|
| 6 | even | 36 | even | |
|
+--------+------+--------+------+ |
|
| 7 | odd | 49 | odd | |
|
+--------+------+--------+------+ |
|
| 8 | even | 64 | even | |
|
+--------+------+--------+------+ |
|
``` |
|
|
|
### To use this library: |
|
|
|
1. Include header with implementation |
|
|
|
```c |
|
#define LIB_TABLE_PRINTER_IMPLEMENTATION |
|
#include <table_printer.h> |
|
``` |
|
|
|
2. Create table printer (wherever you want Stack/Heap) |
|
|
|
```c |
|
table_printer printer = {}; |
|
``` |
|
|
|
3. Declare columns with their widths |
|
|
|
```c |
|
table_printer_push_column(&table, .label = "N", .width = 6); |
|
table_printer_push_column(&table, .width = 4, .align=TableAlign_Left); |
|
table_printer_push_column(&table, .label = "Square", .width = 6); |
|
table_printer_push_column(&table, .width = 4, .align=TableAlign_Left); |
|
``` |
|
|
|
4. Print header (optional) |
|
|
|
```c |
|
table_printer_print_header(&table); |
|
``` |
|
|
|
5. Start printing rows of the table in a loop: |
|
|
|
```c |
|
int i; |
|
for (i = 4; i < 9; i++) |
|
{ |
|
table_printer_print_column(&table, "%d", i); |
|
table_printer_print_column(&table, "%s", i % 2 == 0 ? "even" : "odd"); |
|
if (i == 5) |
|
table_printer_skip_column(&table); |
|
else |
|
table_printer_print_column(&table, "%d", i * i); |
|
table_printer_print_column(&table, "%s", (i * i) % 2 == 0 ? "even" : "odd"); |
|
} |
|
``` |
|
*/ |
|
|
|
#ifndef LIB_TABLE_PRINTER_H |
|
#define LIB_TABLE_PRINTER_H |
|
|
|
char const *spaces = " "; |
|
char const *dashes = "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"; |
|
|
|
typedef enum { |
|
TableAlign_Right, |
|
TableAlign_Left, |
|
} table_printer_alignment; |
|
|
|
typedef struct { |
|
char const *labels[32]; |
|
int widths[32]; |
|
table_printer_alignment aligns[32]; |
|
int count; |
|
int index; |
|
int print_started; |
|
} table_printer; |
|
|
|
typedef struct { |
|
const char *label; |
|
int width; |
|
table_printer_alignment align; |
|
} table_printer_column_arguments; |
|
|
|
#define TABLE_PRINTER_STRINGIFY_(X) #X |
|
#define TABLE_PRINTER_STRINGIFY(X) TABLE_PRINTER_STRINGIFY_(X) |
|
#define table_printer_push_column(PRINTER, ...) table_printer_push_column_args(PRINTER, (table_printer_column_arguments){__VA_ARGS__}) |
|
void table_printer_push_column_args(table_printer *printer, table_printer_column_arguments args); |
|
|
|
void table_printer_push_column_impl(table_printer *printer, char const *label, int width, table_printer_alignment align); |
|
void table_printer_print_column(table_printer *printer, char const *fmt, ...); |
|
void table_printer_print_separator(table_printer *printer); |
|
void table_printer_print_header(table_printer *printer); |
|
|
|
#endif // LIB_TABLE_PRINTER_H |
|
|
|
#ifdef LIB_TABLE_PRINTER_IMPLEMENTATION |
|
#include <stdio.h> |
|
#include <stdarg.h> |
|
|
|
void table_printer_push_column_args(table_printer *printer, table_printer_column_arguments args) |
|
{ |
|
table_printer_push_column_impl(printer, args.label ? args.label : "", args.width > 0 ? args.width : 3, args.align); |
|
} |
|
|
|
void table_printer_push_column_impl(table_printer *printer, char const *label, int width, table_printer_alignment align) |
|
{ |
|
printer->labels[printer->count] = label; |
|
printer->widths[printer->count] = width; |
|
printer->aligns[printer->count] = align; |
|
printer->count += 1; |
|
} |
|
|
|
void table_printer_print_column(table_printer *printer, char const *fmt, ...) |
|
{ |
|
if (printer->print_started == 0) |
|
{ |
|
table_printer_print_separator(printer); |
|
printer->print_started = 1; |
|
} |
|
|
|
char buffer[1024]; |
|
va_list args; |
|
va_start(args, fmt); |
|
int buffer_len = vsnprintf(buffer, sizeof(buffer), fmt, args); |
|
va_end(args); |
|
|
|
int w = printer->widths[printer->index] - buffer_len + 1; |
|
|
|
if (w < 0) w = 0; |
|
int left_pad = 0; |
|
int right_pad = 0; |
|
table_printer_alignment align = printer->aligns[printer->index]; |
|
if (align == TableAlign_Left) |
|
{ |
|
left_pad = 1; |
|
right_pad = w; |
|
} |
|
else if (align == TableAlign_Right) |
|
{ |
|
left_pad = w; |
|
right_pad = 1; |
|
} |
|
|
|
printf("|%.*s%s%.*s", left_pad, spaces, buffer, right_pad, spaces); |
|
printer->index += 1; |
|
if (printer->index == printer->count) |
|
{ |
|
printf("|\n"); |
|
table_printer_print_separator(printer); |
|
printer->index = 0; |
|
} |
|
} |
|
|
|
void table_printer_skip_column(table_printer *printer) |
|
{ |
|
table_printer_print_column(printer, ""); |
|
} |
|
|
|
void table_printer_print_separator(table_printer *printer) |
|
{ |
|
int i; |
|
for (i = 0; i < printer->count; i++) |
|
{ |
|
printf("+%.*s", printer->widths[i] + 2, dashes); |
|
} |
|
printf("+\n"); |
|
} |
|
|
|
void table_printer_print_header(table_printer *printer) |
|
{ |
|
int i; |
|
for (i = 0; i < printer->count; i++) |
|
{ |
|
table_printer_print_column(printer, "%s", printer->labels[i]); |
|
} |
|
printer->print_started = 1; |
|
} |
|
|
|
#endif /* LIB_TABLE_PRINTER_IMPLEMENTATION */ |