rsys

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

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 }