rsys

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

cstr.h (5242B)


      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 #ifndef CSTR_H
     17 #define CSTR_H
     18 
     19 #include "rsys.h"
     20 
     21 #include "math.h"
     22 
     23 #include <errno.h>
     24 #include <float.h>
     25 #include <limits.h>
     26 #include <stdlib.h>
     27 
     28 enum size_unit {
     29   SIZE_BYTE = BIT(0),
     30   SIZE_KBYTE = BIT(1),
     31   SIZE_MBYTE = BIT(2),
     32   SIZE_GBYTE = BIT(3),
     33   SIZE_TBYTE = BIT(4),
     34   SIZE_ALL = -1
     35 };
     36 
     37 static INLINE res_T
     38 cstr_to_double(const char* str, double* dst)
     39 {
     40   char* end;
     41   ASSERT(dst);
     42   if(!str) return RES_BAD_ARG;
     43   *dst = strtod(str, &end);
     44   if(end == str)
     45     return RES_BAD_ARG;
     46   for(;*end != '\0'; ++end) {
     47     if(*end != ' ' && *end != '\t')
     48       return RES_BAD_ARG;
     49   }
     50   return RES_OK;
     51 }
     52 
     53 static INLINE res_T
     54 cstr_to_float(const char* str, float* dst)
     55 {
     56   double dbl;
     57   double tmp;
     58   res_T res;
     59   ASSERT(dst);
     60   res = cstr_to_double(str, &dbl);
     61   if(res != RES_OK)  return res;
     62   tmp = fabs(dbl);
     63   if(tmp != INF && tmp > 0.0 && (tmp < FLT_MIN || tmp > FLT_MAX))
     64     return RES_BAD_ARG;
     65   *dst = (float)dbl;
     66   return RES_OK;
     67 }
     68 
     69 static INLINE res_T
     70 cstr_to_long(const char* str, long* dst)
     71 {
     72   char* end;
     73   ASSERT(dst);
     74   if(!str) return RES_BAD_ARG;
     75   errno = 0;
     76   *dst = strtol(str, &end, 10/* base */);
     77   if(end == str || errno == ERANGE)
     78     return RES_BAD_ARG;
     79   for(;*end != '\0'; ++end) {
     80     if(*end != ' ' && *end != '\t')
     81       return RES_BAD_ARG;
     82   }
     83   return RES_OK;
     84 }
     85 
     86 static INLINE res_T
     87 cstr_to_int(const char* str, int* dst)
     88 {
     89   long l;
     90   res_T res;
     91   ASSERT(dst);
     92   res = cstr_to_long(str, &l);
     93   if(res != RES_OK)
     94     return res;
     95   if(l > INT_MAX || l < INT_MIN)
     96     return RES_BAD_ARG;
     97   *dst = (int)l;
     98   return RES_OK;
     99 }
    100 
    101 static INLINE res_T
    102 cstr_to_ulong(const char* str, unsigned long* dst)
    103 {
    104   char* end;
    105   ASSERT(dst);
    106   if (!str) return RES_BAD_ARG;
    107   errno = 0;
    108   *dst = strtoul(str, &end, 10/* base */);
    109   if(end == str || errno == ERANGE)
    110     return RES_BAD_ARG;
    111   ASSERT(errno == 0);
    112   for(; *end != '\0'; ++end) {
    113     if(*end != ' ' && *end != '\t')
    114       return RES_BAD_ARG;
    115   }
    116   return RES_OK;
    117 }
    118 
    119 static INLINE res_T
    120 cstr_to_uint(const char* str, unsigned* dst)
    121 {
    122   res_T res;
    123   ASSERT(dst);
    124 #if UINT_MAX == ULONG_MAX
    125   {
    126     unsigned long l;
    127     res = cstr_to_ulong(str, &l);
    128     if(res != RES_OK) return res;
    129     *dst = (unsigned)l;
    130   }
    131 #else /* UINT_MAX < ULONG_MAX */
    132   {
    133     long l;
    134     res = cstr_to_long(str, &l);
    135     if(res != RES_OK) return res;
    136     if(l > UINT_MAX) return RES_BAD_ARG;
    137     *dst = (unsigned)l;
    138   }
    139 #endif
    140   return RES_OK;
    141 }
    142 
    143 static INLINE const char*
    144 res_to_cstr(const res_T res)
    145 {
    146   const char* cstr = NULL;
    147   switch(res) {
    148     case RES_OK: cstr = "Success"; break;
    149     case RES_BAD_ARG: cstr = "Invalid argument"; break;
    150     case RES_MEM_ERR: cstr = "Could not allocate memory"; break;
    151     case RES_IO_ERR: cstr = "Input/Ouput error"; break;
    152     case RES_UNKNOWN_ERR: cstr = "Unknown error"; break;
    153     case RES_BAD_OP: cstr = "Invalid operation"; break;
    154     case RES_EOF: cstr = "Reached end of file"; break;
    155     default: FATAL("Ureachable code.\n"); break;
    156   }
    157   return cstr;
    158 }
    159 
    160 BEGIN_DECLS
    161 
    162 /* Parse a string representing a list whose its elements are separated by the
    163  * 'delimeter' char. The functor 'parse_element' is invoked on each element of
    164  * the list. If it notifies an error, i.e. if the parsing of an element failed,
    165  * the overall parsing is instantly stopped and the error is returned to the
    166  * caller */
    167 RSYS_API res_T
    168 cstr_parse_list
    169   (const char* str,
    170    const char delimiter,
    171    res_T (*parse_element)(const char* elmt, void* ctx),
    172    void* ctx); /* User defined data sent to 'parse_element' */
    173 
    174 /* Convert a string "A:B:C:D:E:F" in a list of { A, B, C, D, E, F }. ':' can be
    175  * any user defined character */
    176 RSYS_API res_T
    177 cstr_to_list_double
    178   (const char* str,
    179    const char delimiter,
    180    double dst[], /* May be NULL */
    181    size_t* length, /* May be NULL. Length of the filled list */
    182    const size_t max_length); /* Maximum size of dst */
    183 
    184 RSYS_API res_T
    185 cstr_to_list_float
    186   (const char* str,
    187    const char delimiter,
    188    float dst[], /* May be NULL */
    189    size_t* length, /* May be NULL. Length of the filled list */
    190    const size_t max_length); /* Maximum size of dst */
    191 
    192 RSYS_API res_T
    193 cstr_to_list_uint
    194   (const char* str,
    195    const char delimiter,
    196    unsigned dst[],
    197    size_t* length,
    198    const size_t max_length);
    199 
    200 RSYS_API void
    201 size_to_cstr
    202   (const size_t size,
    203    const int flag, /* Combination of size_unit */
    204    size_t* real_cstr_len, /* May be NULL (does not handle null char) */
    205    char* cstr, /* May be NULL */
    206    const size_t sizeof_cstr); /* Include null char */
    207 
    208 END_DECLS
    209 
    210 #endif /* CSTR_H */