rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit ee9242b65847d58d08b93abb9ce4cd5e51413d78
parent bb949e4e15c4ecb5a0daae58ed067fb841a147c8
Author: vaplv <vaplv@free.fr>
Date:   Mon, 22 Aug 2022 10:12:36 +0200

Merge branch 'develop' into feature_posix_make

Diffstat:
Msrc/clock_time.c | 5+++--
Msrc/clock_time.h | 4++--
Msrc/cstr.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/cstr.h | 17+++++++++++++++++
Msrc/test_cstr.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_time.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
6 files changed, 304 insertions(+), 20 deletions(-)

diff --git a/src/clock_time.c b/src/clock_time.c @@ -157,7 +157,7 @@ time_dump ASSERT(time && (!max_dump_len || dump)); if(real_dump_len) *real_dump_len = 0; - if(dump) dump[0] = '\0'; + if(max_dump_len > 0) dump[0] = '\0'; if(!flag) return; #define DUMP(Time, Suffix) \ @@ -216,7 +216,7 @@ time_dump /* Remove last space */ if(real_dump_len) *real_dump_len -= 1; - if(dump) { + if(max_dump_len > 0) { size_t dump_len = strlen(dump); if(!dump_len && flag) { if(flag & TIME_NSEC) { DUMP(0, "nsec"); @@ -225,6 +225,7 @@ time_dump } else if(flag & TIME_SEC) { DUMP(0, "sec"); } else if(flag & TIME_MIN) { DUMP(0, "min"); } else if(flag & TIME_HOUR) { DUMP(0, "hour"); + } else if(flag & TIME_DAY) { DUMP(0, "day"); } dump_len = strlen(dump); } diff --git a/src/clock_time.h b/src/clock_time.h @@ -72,9 +72,9 @@ RSYS_API void time_dump (const struct time* time, int flag, /* Combination of time_unit or TIME_ALL */ - size_t* real_dump_len, /* May be NULL */ + size_t* real_dump_len, /* May be NULL (wo '\0') */ char* dump, /* May be NULL */ - size_t max_dump_len); + size_t max_dump_len); /* With '\0' */ END_DECLS diff --git a/src/cstr.c b/src/cstr.c @@ -28,7 +28,7 @@ #define CSTR_LIST_SUFFIX uint #include "cstr_to_list.h" -RSYS_API res_T +res_T cstr_parse_list (const char* str, const char delimiter, @@ -68,3 +68,94 @@ error: goto exit; } +void +size_to_cstr + (const size_t size_byte, + const int flag, /* Combination of size_unit */ + size_t* real_cstr_len, /* May be NULL */ + char* cstr, /* May be NULL */ + const size_t sizeof_cstr) +{ + size_t available_cstr_space = sizeof_cstr; + size_t size = size_byte; + char* dst = cstr; + ASSERT((!sizeof_cstr || cstr)); + ASSERT(size_byte <= INT64_MAX); + + if(real_cstr_len) *real_cstr_len = 0; + if(sizeof_cstr > 0) cstr[0] = '\0'; + if(!flag) return; + + #define NBYTES_PER_KBYTE ((size_t)1024) + #define NBYTES_PER_MBYTE ((size_t)1024 * NBYTES_PER_KBYTE) + #define NBYTES_PER_GBYTE ((size_t)1024 * NBYTES_PER_MBYTE) + #define NBYTES_PER_TBYTE ((size_t)1024 * NBYTES_PER_GBYTE) + + #define DUMP(Size, Suffix) \ + { \ + const int len = snprintf \ + (dst, available_cstr_space, "%li %s ", (long)Size, Suffix); \ + ASSERT(len >= 0); \ + if(real_cstr_len) { \ + *real_cstr_len += (size_t)len; \ + } \ + if((size_t)len < available_cstr_space) { \ + dst += len; \ + available_cstr_space -= (size_t)len; \ + } else if(dst) { \ + available_cstr_space = 0; \ + dst = NULL; \ + } \ + } (void) 0 + + if(flag & SIZE_TBYTE) { + const size_t nb_teras = size / NBYTES_PER_TBYTE; + if(nb_teras) DUMP(nb_teras, "TB"); + size -= nb_teras * NBYTES_PER_TBYTE; + } + if(flag & SIZE_GBYTE) { + const size_t nb_gigas = size / NBYTES_PER_GBYTE; + if(nb_gigas) DUMP(nb_gigas, "GB"); + size -= nb_gigas * NBYTES_PER_GBYTE; + } + if(flag & SIZE_MBYTE) { + const size_t nb_megas = size / NBYTES_PER_MBYTE; + if(nb_megas) DUMP(nb_megas, "MB"); + size -= nb_megas * NBYTES_PER_MBYTE; + } + if(flag & SIZE_KBYTE) { + const size_t nb_kilos = size / NBYTES_PER_KBYTE; + if(nb_kilos) DUMP(nb_kilos, "KB"); + size -= nb_kilos * NBYTES_PER_KBYTE; + } + if(flag & SIZE_BYTE) { + if(size) DUMP(size, "B"); + } + + /* Remove last space */ + if(real_cstr_len) *real_cstr_len -= 1; + + if(sizeof_cstr > 0) { + size_t cstr_len = strlen(cstr); + + if(!cstr_len && flag) { + ASSERT(size_byte == 0); + if(flag & SIZE_BYTE) { DUMP(0, "B"); + } else if(flag & SIZE_KBYTE) { DUMP(0, "KB"); + } else if(flag & SIZE_MBYTE) { DUMP(0, "MB"); + } else if(flag & SIZE_GBYTE) { DUMP(0, "GB"); + } else if(flag & SIZE_TBYTE) { DUMP(0, "TB"); + } + cstr_len = strlen(cstr); + } + /* Remove last space */ + if(cstr[cstr_len-1] == ' ') { + cstr[cstr_len-1] = '\0'; + } + } + #undef NBYTES_PER_KBYTE + #undef NBYTES_PER_MBYTE + #undef NBYTES_PER_GBYTE + #undef NBYTES_PER_TBYTE + #undef DUMP +} diff --git a/src/cstr.h b/src/cstr.h @@ -25,6 +25,15 @@ #include <limits.h> #include <stdlib.h> +enum size_unit { + SIZE_BYTE = BIT(0), + SIZE_KBYTE = BIT(1), + SIZE_MBYTE = BIT(2), + SIZE_GBYTE = BIT(3), + SIZE_TBYTE = BIT(4), + SIZE_ALL = -1 +}; + static INLINE res_T cstr_to_double(const char* str, double* dst) { @@ -188,6 +197,14 @@ cstr_to_list_uint size_t* length, const size_t max_length); +RSYS_API void +size_to_cstr + (const size_t size, + const int flag, /* Combination of size_unit */ + size_t* real_cstr_len, /* May be NULL (does not handle null char) */ + char* cstr, /* May be NULL */ + const size_t sizeof_cstr); /* Include null char */ + END_DECLS #endif /* CSTR_H */ diff --git a/src/test_cstr.c b/src/test_cstr.c @@ -343,6 +343,102 @@ test_res_to_cstr(void) printf("%s\n", res_to_cstr(RES_EOF)); } +static INLINE size_t +size + (const size_t teras, + const size_t gigas, + const size_t megas, + const size_t kilos, + const size_t bytes) +{ + return (size_t)1024*((size_t)1024*((size_t)1024*((size_t)1024* + teras + gigas) + megas) + kilos) + bytes; +} + +static void +test_size_to_cstr(void) +{ + char dump[512]; + size_t len; + size_t sz; + size_t dump_len; + char* tk = 0; + + sz = size(2, 450, 987, 243, 42); + + size_to_cstr(sz, SIZE_ALL, &len, NULL, 0); + CHK(len == 30); + size_to_cstr(sz, SIZE_ALL, NULL, dump, sizeof(dump)); + printf("%s\n", dump); + dump_len = strlen(dump); + CHK(len == dump_len); + + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "2")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "TB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "450")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "GB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "987")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "MB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "243")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "KB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "42")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "B")); + CHK((tk = strtok(NULL, " ")) == NULL); + + /* Check string truncation */ + size_to_cstr(sz, SIZE_ALL, &len, dump, dump_len - 3 + 1/*null char*/); + CHK(len == 30); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "2")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "TB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "450")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "GB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "987")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "MB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "243")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "KB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "4")); + CHK((tk = strtok(NULL, " ")) == NULL); + + size_to_cstr(sz, SIZE_GBYTE|SIZE_MBYTE, &len, dump, sizeof(dump)); + CHK(len == strlen(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "2498")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "GB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "987")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "MB")); + CHK((tk = strtok(NULL, " ")) == NULL); + + size_to_cstr(sz, SIZE_GBYTE|SIZE_KBYTE|SIZE_BYTE, &len, dump, sizeof(dump)); + CHK(len == strlen(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "2498")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "GB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "1010931")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "KB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "42")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "B")); + CHK((tk = strtok(NULL, " ")) == NULL); + + size_to_cstr(sz, 0, &len, dump, sizeof(dump)); + CHK(len == 0 && dump[0] == '\0'); + + size_to_cstr(0, SIZE_ALL, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "0")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "B")); + CHK((tk = strtok(NULL, " ")) == NULL); + + size_to_cstr(0, SIZE_TBYTE, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "0")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "TB")); + CHK((tk = strtok(NULL, " ")) == NULL); + + sz = size(0, 3, 0, 17, 0); + size_to_cstr(sz, SIZE_ALL, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "3")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "GB")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "17")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "KB")); + CHK((tk = strtok(NULL, " ")) == NULL); +} + int main(int argc, char** argv) { @@ -358,5 +454,6 @@ main(int argc, char** argv) test_list_float(); test_list_uint(); test_res_to_cstr(); + test_size_to_cstr(); return 0; } diff --git a/src/test_time.c b/src/test_time.c @@ -17,12 +17,36 @@ #include <stdlib.h> #include <string.h> +static struct time +build_time + (const int64_t days, + const int64_t hours, + const int64_t mins, + const int64_t secs, + const int64_t msecs, + const int64_t usecs, + const int64_t nsecs) +{ + struct time t; + + t.sec = days * 3600 * 24; + t.sec += hours * 3600; + t.sec += mins * 60; + t.sec += secs; + + t.nsec = msecs * 1000000; + t.nsec += usecs * 1000; + t.nsec += nsecs; + + return t; +} + int main(int argc, char** argv) { struct time start, end, res; char dump[512]; - char buf[32]; + char* tk; int64_t time = 0; int64_t i = 0; size_t dump_len; @@ -42,14 +66,14 @@ main(int argc, char** argv) time_dump (&res, TIME_SEC|TIME_MSEC|TIME_USEC, &dump_len, dump, sizeof(dump)); CHK(dump_len == strlen(dump)); - printf(">>> %s.\n", dump); + printf("%s\n", dump); time_dump(&res, TIME_ALL, NULL, dump, sizeof(dump)); - printf(">>> %s.\n", dump); + printf("%s\n", dump); CHK(time_add(&res, &res, &res) == &res); CHK(time_val(&res, TIME_NSEC) == 2*time); time_dump(&res, TIME_ALL, NULL, dump, sizeof(dump)); - printf(">>> %s.\n", dump); + printf("%s\n", dump); time = time_val(&res, TIME_NSEC); CHK(time_zero(&start) == &start); @@ -63,20 +87,74 @@ main(int argc, char** argv) CHK(time_sub(&res, &end, &end) == &res); CHK(time_val(&res, TIME_NSEC) == 0); + + res = build_time(1, 10, 55, 30, 998, 763, 314); + dump[0] = '?'; + time_dump(&res, TIME_ALL, &dump_len, dump, 0); + CHK(dump[0] = '?'); time_dump(&res, TIME_ALL, NULL, dump, sizeof(dump)); - printf(">>> %s.\n", dump); - time_dump(&res, 0, NULL, dump, sizeof(dump)); - printf(">>> %s.\n", dump); + CHK(dump_len == strlen(dump)); - res.sec = 5; - res.nsec = 524198207; - time_dump(&res, TIME_ALL, &dump_len, buf, sizeof(buf)); - CHK(dump_len >= strlen(buf)); - printf(">>> %s.\n", buf); + printf("%s\n", dump); - time_dump(&res, TIME_ALL, &dump_len, dump, sizeof(dump)); - CHK(dump_len >= strlen(dump)); - printf(">>> %s.\n", dump); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "1")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "day")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "10")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "hours")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "55")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "mins")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "30")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "secs")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "998")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "msecs")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "763")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "usecs")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "314")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "nsecs")); + CHK((tk = strtok(NULL, " ")) == NULL); + /* Check string truncation */ + time_dump(&res, TIME_ALL, NULL, dump, dump_len - 27 + 1/*null char*/); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "1")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "day")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "10")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "hours")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "55")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "mins")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "30")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "secs")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "99")); + CHK((tk = strtok(NULL, " ")) == NULL); + + time_dump(&res, TIME_MIN|TIME_MSEC, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "2095")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "mins")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "30998")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "msecs")); + CHK((tk = strtok(NULL, " ")) == NULL); + + time_dump(&res, 0, &dump_len, dump, sizeof(dump)); + CHK(dump_len == 0 && dump[0] == '\0'); + + res = build_time(0, 0, 0, 0, 0, 0, 0); + time_dump(&res, TIME_ALL, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "0")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "nsec")); + CHK((tk = strtok(NULL, " ")) == NULL); + + time_dump(&res, TIME_DAY, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "0")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "day")); + CHK((tk = strtok(NULL, " ")) == NULL); + + res = build_time(0, 0, 1, 0, 235, 10, 0); + time_dump(&res, TIME_ALL, NULL, dump, sizeof(dump)); + CHK((tk = strtok(dump, " ")) && !strcmp(tk, "1")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "min")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "235")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "msecs")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "10")); + CHK((tk = strtok(NULL, " ")) && !strcmp(tk, "usecs")); + CHK((tk = strtok(NULL, " ")) == NULL); return 0; }