15 enum fmt_types { AT_STRING, AT_FLOAT, AT_DOUBLE, AT_COMPLEX,
16 AT_SHORTSHORT, AT_SHORT, AT_INT, AT_LONG, AT_LONGLONG,
17 AT_USHORTSHORT, AT_USHORT, AT_UINT, AT_ULONG, AT_ULONGLONG };
26 int count_complex_formats(
const char* fmt_str) {
27 const char * fmt_regex =
"%([[:digit:]]+\\$)?[+-]?([ 0]|\'.{1})?-?[[:digit:]]*(\\.[[:digit:]]+)?[lhjztL]*[eEfFgG]" 28 "%([[:digit:]]+\\$)?[+-]([ 0]|\'.{1})?-?[[:digit:]]*(\\.[[:digit:]]+)?[lhjztL]*[eEfFgG]j";
29 int ret = count_matches(fmt_regex, fmt_str);
43 int count_formats(
const char* fmt_str) {
44 const char * fmt_regex =
"%([[:digit:]]+\\$)?[+-]?([ 0]|\'.{1})?-?[[:digit:]]*(\\.[[:digit:]]+)?[lhjztL]*(64)?[bcdeEufFgGosxX]";
45 int ret = count_matches(fmt_regex, fmt_str);
59 int simplify_formats(
char *fmt_str,
const size_t fmt_len) {
60 const char * fmt_regex1 =
"%([[:digit:]]+\\$)?[+-]?([ 0]|\'.{1})?-?[[:digit:]]*(\\.[[:digit:]]+)?([lhjztL]*)([eEfFgG])";
63 int ret = regex_replace_sub(fmt_str, fmt_len, fmt_regex1,
66 const char * fmt_regex2 =
"%[lhjztL]*([fF])";
67 ret = regex_replace_sub(fmt_str, fmt_len, fmt_regex2,
98 return af_open(&((*t).f));
121 int at_readline_full_realloc(
const asciiTable_t t,
char **buf,
122 const size_t len_buf,
const int allow_realloc) {
124 int ret = 0, com = 1;
125 size_t nread = LINE_SIZE_MAX;
126 char *line = (
char*)malloc(nread);
128 cislog_error(
"at_readline_full_realloc: Failed to malloc line.");
131 while ((ret >= 0) && (com == 1)) {
132 ret = af_readline_full(t.
f, &line, &nread);
137 com = af_is_comment(t.
f, line);
139 if (ret > (
int)len_buf) {
141 cislog_debug(
"at_readline_full_realloc: reallocating buffer from %d to %d bytes.",
142 (
int)len_buf, ret + 1);
143 char *temp_buf = (
char*)realloc(*buf, ret + 1);
144 if (temp_buf == NULL) {
145 cislog_error(
"at_readline_full_realloc: Failed to realloc buffer.");
152 cislog_error(
"at_readline_full_realloc: line (%d bytes) is larger than destination buffer (%d bytes)",
173 int at_readline_full(
const asciiTable_t t,
char *buf,
const size_t len_buf) {
175 return at_readline_full_realloc(t, &buf, len_buf, 0);
185 int at_writeline_full(
const asciiTable_t t,
const char* line) {
187 ret = af_writeline_full(t.
f, line);
200 int at_vbytes_to_row(
const asciiTable_t t,
const char* line, va_list ap) {
202 char fmt[LINE_SIZE_MAX];
204 int sret = simplify_formats(fmt, LINE_SIZE_MAX);
206 cislog_debug(
"at_vbytes_to_row: simplify_formats returned %d", sret);
210 int ret = vsscanf(line, fmt, ap);
211 if (ret != t.
ncols) {
212 cislog_error(
"at_vbytes_to_row: %d arguments filled, but %d were expected",
230 int at_vrow_to_bytes(
const asciiTable_t t,
char *buf,
const size_t buf_siz, va_list ap) {
231 int ret = vsnprintf(buf, buf_siz, t.
format_str, ap);
246 size_t nread = LINE_SIZE_MAX;
247 char *line = (
char*)malloc(nread);
249 cislog_error(
"at_vreadline: Failed to malloc line.");
252 ret = at_readline_full(t, line, nread);
258 int sret = at_vbytes_to_row(t, line, ap);
289 int ret = at_vreadline(t, ap);
305 int ret = at_vwriteline(t, ap);
318 if (af_is_open(t.
f) == 1) {
335 int ret = at_open(t);
338 size_t nread = LINE_SIZE_MAX;
339 char *line = (
char*)malloc(nread);
341 cislog_error(
"at_discover_format_str: Failed to malloc line.");
345 while (getline(&line, &nread, (*t).f.fd) >= 0) {
346 if (af_is_comment((*t).f, line) == 1) {
347 if (count_formats(line) > 0) {
348 strcpy((*t).format_str, line + strlen((*t).f.comment));
368 count = count_formats((*t).format_str);
384 for (i = 0; i < (*t).ncols; i++) {
385 typ = (*t).format_typ[i];
386 siz = (*t).format_siz[i];
387 if (typ == AT_STRING) siz = (*t).format_siz[i];
388 else if (typ == AT_FLOAT) siz =
sizeof(float);
389 else if (typ == AT_DOUBLE) siz =
sizeof(double);
390 else if (typ == AT_COMPLEX) siz = 2*
sizeof(double);
391 else if (typ == AT_SHORTSHORT) siz =
sizeof(char);
392 else if (typ == AT_SHORT) siz =
sizeof(short);
393 else if (typ == AT_LONGLONG) siz =
sizeof(
long long);
394 else if (typ == AT_LONG) siz =
sizeof(long);
395 else if (typ == AT_INT) siz =
sizeof(int);
396 else if (typ == AT_USHORTSHORT) siz =
sizeof(
unsigned char);
397 else if (typ == AT_USHORT) siz =
sizeof(
unsigned short);
398 else if (typ == AT_ULONGLONG) siz =
sizeof(
unsigned long long);
399 else if (typ == AT_ULONG) siz =
sizeof(
unsigned long);
400 else if (typ == AT_UINT) siz =
sizeof(
unsigned int);
403 cislog_error(
"at_set_format_siz: Could not set size for column %d with type %d", i, typ);
406 (*t).format_siz[i] = siz;
422 (*t).format_typ = (
int*)malloc((*t).ncols*
sizeof(
int));
423 (*t).format_siz = (
int*)malloc((*t).ncols*
sizeof(
int));
424 if (((*t).format_typ == NULL) || ((*t).format_siz == NULL)) {
425 cislog_error(
"at_set_format_typ: Failed to alloc format_typ/format_siz");
432 for (icol = 0; icol < (*t).ncols; icol++) {
433 (*t).format_typ[icol] = -1;
434 (*t).format_siz[icol] = -1;
440 char re_fmt[FMT_LEN];
441 sprintf(re_fmt,
"%%[^%s%s]+[%s%s]",
442 (*t).column, (*t).f.newline, (*t).column, (*t).f.newline);
443 while (beg < strlen((*t).format_str)) {
444 mres = find_match(re_fmt, (*t).format_str + beg, &sind, &eind);
446 cislog_error(
"at_set_format_typ: find_match returned %d", mres);
448 }
else if (mres == 0) {
453 end = beg + (eind - sind);
454 strncpy(ifmt, &((*t).format_str)[beg], end-beg);
455 ifmt[end-beg] =
'\0';
456 if (find_match(
"%.*s", ifmt, &sind, &eind)) {
457 (*t).format_typ[icol] = AT_STRING;
458 mres = regex_replace_sub(ifmt, FMT_LEN,
459 "%(\\.)?([[:digit:]]*)s(.*)",
"$2", 0);
460 (*t).format_siz[icol] = atoi(ifmt);
462 }
else if (find_match(
"(%.*[fFeEgG]){2}j", ifmt, &sind, &eind)) {
464 }
else if (find_match(
"(\%.*[fFeEgG]){2}j", ifmt, &sind, &eind)) {
467 (*t).format_typ[icol] = AT_DOUBLE;
469 (*t).format_typ[icol] = AT_DOUBLE;
470 }
else if (find_match(
"%.*[fFeEgG]", ifmt, &sind, &eind)) {
471 (*t).format_typ[icol] = AT_DOUBLE;
476 }
else if (find_match(
"%.*hh[id]", ifmt, &sind, &eind)) {
477 (*t).format_typ[icol] = AT_SHORTSHORT;
478 }
else if (find_match(
"%.*h[id]", ifmt, &sind, &eind)) {
479 (*t).format_typ[icol] = AT_SHORT;
480 }
else if (find_match(
"%.*ll[id]", ifmt, &sind, &eind)) {
481 (*t).format_typ[icol] = AT_LONGLONG;
482 }
else if (find_match(
"%.*l64[id]", ifmt, &sind, &eind)) {
483 (*t).format_typ[icol] = AT_LONGLONG;
484 }
else if (find_match(
"%.*l[id]", ifmt, &sind, &eind)) {
485 (*t).format_typ[icol] = AT_LONG;
486 }
else if (find_match(
"%.*[id]", ifmt, &sind, &eind)) {
487 (*t).format_typ[icol] = AT_INT;
488 }
else if (find_match(
"%.*hh[uoxX]", ifmt, &sind, &eind)) {
489 (*t).format_typ[icol] = AT_USHORTSHORT;
490 }
else if (find_match(
"%.*h[uoxX]", ifmt, &sind, &eind)) {
491 (*t).format_typ[icol] = AT_USHORT;
492 }
else if (find_match(
"%.*ll[uoxX]", ifmt, &sind, &eind)) {
493 (*t).format_typ[icol] = AT_ULONGLONG;
494 }
else if (find_match(
"%.*l64[uoxX]", ifmt, &sind, &eind)) {
495 (*t).format_typ[icol] = AT_ULONGLONG;
496 }
else if (find_match(
"%.*l[uoxX]", ifmt, &sind, &eind)) {
497 (*t).format_typ[icol] = AT_ULONG;
498 }
else if (find_match(
"%.*[uoxX]", ifmt, &sind, &eind)) {
499 (*t).format_typ[icol] = AT_UINT;
501 cislog_error(
"at_set_format_typ: Could not parse format string: %s", ifmt);
507 return at_set_format_siz(t);
521 int at_vbytes_to_array(
const asciiTable_t t,
const char *data,
522 const size_t data_siz, va_list ap) {
525 if ((data_siz % t.
row_siz) != 0) {
526 cislog_error(
"at_vbytes_to_array: Data: %s", data);
527 cislog_error(
"at_vbytes_to_array: Data size (%d) not an even number of rows (row size is %d)",
532 int nrows = (int)data_siz / t.
row_siz;
533 int cur_pos = 0, col_siz;
535 for (i = 0; i < t.
ncols; i++) {
538 temp = va_arg(ap,
char**);
540 t2 = (
char*)realloc(*temp, col_siz);
542 cislog_error(
"at_vbytes_to_array: Failed to realloc temp var.");
553 memcpy(*temp, data+cur_pos, col_siz);
574 int at_varray_to_bytes(
const asciiTable_t t,
char *data,
const size_t data_siz, va_list ap) {
575 int nrows = va_arg(ap,
int);
577 if (msg_siz > (
int)data_siz) {
578 cislog_debug(
"at_varray_to_bytes: Message size (%d bytes) will exceed allocated buffer (%d bytes).",
579 msg_siz, (
int)data_siz);
583 int cur_pos = 0, col_siz;
586 for (i = 0; i < t.
ncols; i++) {
588 temp = va_arg(ap,
char*);
589 memcpy(data+cur_pos, temp, col_siz);
606 int at_bytes_to_array(
const asciiTable_t t,
char *data,
size_t data_siz, ...) {
608 va_start(ap, data_siz);
609 int ret = at_vbytes_to_array(t, data, data_siz, ap);
626 int at_array_to_bytes(
const asciiTable_t t,
char *data,
const size_t data_siz, ...) {
628 va_start(ap, data_siz);
629 int ret = at_varray_to_bytes(t, data, data_siz, ap);
641 free((*t).format_typ);
643 free((*t).format_siz);
644 (*t).format_typ = NULL;
645 (*t).format_siz = NULL;
657 int at_update(
asciiTable_t *t,
const char *filepath,
const char *io_mode) {
659 flag = af_update(&(t->
f), filepath, io_mode);
661 if ((strlen(t->
format_str) == 0) && (strcmp(io_mode,
"r") == 0)) {
662 flag = at_discover_format_str(t);
664 flag = at_set_ncols(t);
666 flag = at_set_format_typ(t);
690 asciiTable_t asciiTable(
const char *filepath,
const char *io_mode,
691 const char *format_str,
const char *comment,
692 const char *column,
const char *newline) {
700 t.
f = asciiFile(filepath, io_mode, comment, newline);
707 if (format_str == NULL) {
708 if (strcmp(io_mode,
"r") == 0) {
709 t.
status = at_discover_format_str(&t);
718 t.
status = at_set_ncols(&t);
720 t.
status = at_set_format_typ(&t);
int row_siz
Size of an entire row in bytes.
Definition: AsciiTable.h:87
int * format_typ
Array of ncols integers specifying column types.
Definition: AsciiTable.h:85
char comment[64]
Character(s) indicating a comment.
Definition: AsciiFile.h:18
char format_str[LINE_SIZE_MAX]
Format string for rows.
Definition: AsciiTable.h:82
asciiFile_t f
ASCII file structure.
Definition: AsciiTable.h:81
int * format_siz
Array of ncols sizes for elements in each column.
Definition: AsciiTable.h:86
char column[64]
Character(s) used to seperate columns.
Definition: AsciiTable.h:83
int ncols
Number of columns in the table.
Definition: AsciiTable.h:84
Structure containing information about an ASCII text file.
Definition: AsciiFile.h:15
FILE * fd
File identifier for ASCII file when open.
Definition: AsciiFile.h:20
Structure containing information about an ASCII table.
Definition: AsciiTable.h:80
int status
Negative if format_str has not been set yet.
Definition: AsciiTable.h:88