cstr.c (5151B)
1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr) 2 * 3 * The RSys library is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published 5 * by the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * The RSys library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #define _POSIX_C_SOURCE 200112L /* strtok_r support */ 17 18 #include "cstr_to_list.h" 19 #include "str.h" 20 21 #define CSTR_LIST_TYPE double 22 #include "cstr_to_list.h" 23 24 #define CSTR_LIST_TYPE float 25 #include "cstr_to_list.h" 26 27 #define CSTR_LIST_TYPE unsigned 28 #define CSTR_LIST_SUFFIX uint 29 #include "cstr_to_list.h" 30 31 res_T 32 cstr_parse_list 33 (const char* str, 34 const char delimiter, 35 res_T (*parse_element)(const char* elmt, void* ctx), 36 void* ctx) /* User defined data sent to 'parse_element' */ 37 { 38 struct str buf; 39 char delim[2] = {'\0', '\0'}; 40 char* tk; 41 char* tk_ctx; 42 res_T res = RES_OK; 43 44 str_init(NULL, &buf); 45 46 if(!str || !parse_element) { 47 res = RES_BAD_ARG; 48 goto error; 49 } 50 51 /* Copy str in a temporary buffer to parse */ 52 res = str_set(&buf, str); 53 if(res != RES_OK) goto error; 54 55 /* Parse the list */ 56 delim[0] = delimiter; 57 tk = strtok_r(str_get(&buf), delim, &tk_ctx); 58 while(tk) { 59 res = parse_element(tk, ctx); 60 if(res != RES_OK) goto error; 61 tk = strtok_r(NULL, delim, &tk_ctx); 62 } 63 64 exit: 65 str_release(&buf); 66 return res; 67 error: 68 goto exit; 69 } 70 71 void 72 size_to_cstr 73 (const size_t size_byte, 74 const int flag, /* Combination of size_unit */ 75 size_t* real_cstr_len, /* May be NULL */ 76 char* cstr, /* May be NULL */ 77 const size_t sizeof_cstr) 78 { 79 size_t available_cstr_space = sizeof_cstr; 80 size_t size = size_byte; 81 char* dst = cstr; 82 ASSERT((!sizeof_cstr || cstr)); 83 ASSERT(size_byte <= INT64_MAX); 84 85 if(real_cstr_len) *real_cstr_len = 0; 86 if(sizeof_cstr > 0) cstr[0] = '\0'; 87 if(!flag) return; 88 89 #define NBYTES_PER_KBYTE ((size_t)1024) 90 #define NBYTES_PER_MBYTE ((size_t)1024 * NBYTES_PER_KBYTE) 91 #define NBYTES_PER_GBYTE ((size_t)1024 * NBYTES_PER_MBYTE) 92 #define NBYTES_PER_TBYTE ((size_t)1024 * NBYTES_PER_GBYTE) 93 94 #define DUMP(Size, Suffix) \ 95 { \ 96 const int len = snprintf \ 97 (dst, available_cstr_space, "%li %s ", (long)Size, Suffix); \ 98 ASSERT(len >= 0); \ 99 if(real_cstr_len) { \ 100 *real_cstr_len += (size_t)len; \ 101 } \ 102 if((size_t)len < available_cstr_space) { \ 103 dst += len; \ 104 available_cstr_space -= (size_t)len; \ 105 } else if(dst) { \ 106 available_cstr_space = 0; \ 107 dst = NULL; \ 108 } \ 109 } (void) 0 110 111 if(flag & SIZE_TBYTE) { 112 const size_t nb_teras = size / NBYTES_PER_TBYTE; 113 if(nb_teras) DUMP(nb_teras, "TB"); 114 size -= nb_teras * NBYTES_PER_TBYTE; 115 } 116 if(flag & SIZE_GBYTE) { 117 const size_t nb_gigas = size / NBYTES_PER_GBYTE; 118 if(nb_gigas) DUMP(nb_gigas, "GB"); 119 size -= nb_gigas * NBYTES_PER_GBYTE; 120 } 121 if(flag & SIZE_MBYTE) { 122 const size_t nb_megas = size / NBYTES_PER_MBYTE; 123 if(nb_megas) DUMP(nb_megas, "MB"); 124 size -= nb_megas * NBYTES_PER_MBYTE; 125 } 126 if(flag & SIZE_KBYTE) { 127 const size_t nb_kilos = size / NBYTES_PER_KBYTE; 128 if(nb_kilos) DUMP(nb_kilos, "KB"); 129 size -= nb_kilos * NBYTES_PER_KBYTE; 130 } 131 if(flag & SIZE_BYTE) { 132 if(size) DUMP(size, "B"); 133 } 134 135 /* Remove last space */ 136 if(real_cstr_len) *real_cstr_len -= 1; 137 138 if(sizeof_cstr > 0) { 139 size_t cstr_len = strlen(cstr); 140 141 if(!cstr_len && flag) { 142 ASSERT(size_byte == 0); 143 if(flag & SIZE_BYTE) { DUMP(0, "B"); 144 } else if(flag & SIZE_KBYTE) { DUMP(0, "KB"); 145 } else if(flag & SIZE_MBYTE) { DUMP(0, "MB"); 146 } else if(flag & SIZE_GBYTE) { DUMP(0, "GB"); 147 } else if(flag & SIZE_TBYTE) { DUMP(0, "TB"); 148 } 149 cstr_len = strlen(cstr); 150 } 151 /* Remove last space */ 152 if(cstr[cstr_len-1] == ' ') { 153 cstr[cstr_len-1] = '\0'; 154 } 155 } 156 #undef NBYTES_PER_KBYTE 157 #undef NBYTES_PER_MBYTE 158 #undef NBYTES_PER_GBYTE 159 #undef NBYTES_PER_TBYTE 160 #undef DUMP 161 }