rsys

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

str.h (4587B)


      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 STR_H
     17 #define STR_H
     18 
     19 #include "hash.h"
     20 #include "mem_allocator.h"
     21 #include "rsys.h"
     22 
     23 #include <stdarg.h>
     24 #include <string.h>
     25 
     26 struct str {
     27   /* Internal data. Should not be publicly accessed */
     28   struct mem_allocator* allocator;
     29   size_t allocated; /* <=> string capacity */
     30   char* cstr;
     31   char buffer[16]; /* static buffer. Avoid allocation on small string */
     32 };
     33 
     34 static INLINE void
     35 str_init(struct mem_allocator* allocator, struct str* str)
     36 {
     37   ASSERT(str);
     38   str->allocator = allocator ? allocator : &mem_default_allocator;
     39   str->allocated = sizeof(str->buffer);
     40   str->cstr = str->buffer;
     41   str->buffer[0] = '\0';
     42 }
     43 
     44 static INLINE void
     45 str_release(struct str* str)
     46 {
     47   ASSERT(str);
     48   if(str->cstr != str->buffer)
     49     MEM_RM(str->allocator, str->cstr);
     50   str->cstr = NULL;
     51 }
     52 
     53 static INLINE size_t
     54 str_len(const struct str* str)
     55 {
     56   ASSERT(str);
     57   return strlen(str->cstr);
     58 }
     59 
     60 static INLINE char
     61 str_is_empty(const struct str* str)
     62 {
     63   ASSERT(str);
     64   return str_len(str) == 0;
     65 }
     66 
     67 static INLINE void
     68 str_clear(struct str* str)
     69 {
     70   ASSERT(str);
     71   str->cstr[0] = '\0';
     72 }
     73 
     74 static INLINE char*
     75 str_get(struct str* str)
     76 {
     77   ASSERT(str);
     78   return str->cstr;
     79 }
     80 
     81 static INLINE const char*
     82 str_cget(const struct str* str)
     83 {
     84   ASSERT(str);
     85   return str->cstr;
     86 }
     87 
     88 static INLINE int
     89 str_cmp(const struct str* str0, const struct str* str1)
     90 {
     91   ASSERT(str0 && str1);
     92   return strcmp(str_cget(str0), str_cget(str1));
     93 }
     94 
     95 static INLINE char
     96 str_eq(const struct str* str0, const struct str* str1)
     97 {
     98   return str_cmp(str0, str1) == 0;
     99 }
    100 
    101 BEGIN_DECLS
    102 
    103 RSYS_API res_T str_set(struct str* str, const char* cstr);
    104 RSYS_API res_T str_insert(struct str* str, const size_t i, const char* cstr);
    105 RSYS_API res_T str_insert_char(struct str* str, const size_t i, const char ch);
    106 RSYS_API res_T str_append(struct str* str, const char* cstr);
    107 RSYS_API res_T str_append_char(struct str* str, const char ch);
    108 RSYS_API res_T str_reserve(struct str* str, const size_t capacity);
    109 
    110 RSYS_API res_T
    111 str_printf
    112   (struct str* str,
    113    const char* fmt,
    114    ...)
    115 #ifdef COMPILER_GCC
    116   __attribute__((format(printf, 2, 3)))
    117 #endif
    118 ;
    119 
    120 RSYS_API res_T
    121 str_append_printf
    122   (struct str* str,
    123    const char* fmt,
    124    ...)
    125 #ifdef COMPILER_GCC
    126   __attribute__((format(printf, 2, 3)))
    127 #endif
    128 ;
    129 
    130 RSYS_API res_T
    131 str_vprintf
    132   (struct str* str,
    133    const char* fmt,
    134    va_list vargs_list);
    135 
    136 RSYS_API res_T
    137 str_append_vprintf
    138   (struct str* str,
    139    const char* fmt,
    140    va_list vargs_list);
    141 
    142 END_DECLS
    143 
    144 static INLINE res_T
    145 str_copy(struct str* dst, const struct str* src)
    146 {
    147   ASSERT(dst && src);
    148   if(dst == src)
    149     return RES_OK;
    150   return str_set(dst, str_cget(src));
    151 }
    152 
    153 static INLINE res_T
    154 str_copy_and_clear(struct str* dst, struct str* src)
    155 {
    156   res_T res = RES_OK;
    157   ASSERT(dst && src);
    158   if(dst == src) {
    159     str_clear(dst);
    160     return RES_OK;
    161   }
    162 
    163   if(src->cstr != src->buffer && src->allocator == dst->allocator) {
    164     /* Give the ownership of src->cstr to dst */
    165     if(dst->cstr != dst->buffer )
    166       MEM_RM(dst->allocator, dst->cstr);
    167     dst->cstr = src->cstr;
    168     dst->allocated = src->allocated;
    169     /* Reset the src to its initial state */
    170     str_init(src->allocator, src);
    171   } else {
    172     res = str_copy(dst, src);
    173     if(res == RES_OK)
    174       str_clear(src);
    175   }
    176   return res;
    177 }
    178 
    179 static INLINE res_T
    180 str_copy_and_release(struct str* dst, struct str* src)
    181 {
    182   res_T res = RES_OK;
    183   ASSERT( dst && src );
    184   if(dst == src) {
    185     str_release(dst);
    186   } else {
    187     res = str_copy_and_clear(dst, src);
    188     if(res == RES_OK)
    189       str_release(src);
    190   }
    191   return res;
    192 }
    193 
    194 static INLINE size_t
    195 str_hash(const struct str* str)
    196 {
    197   const char* c_str;
    198   ASSERT(str);
    199   c_str = str_cget(str);
    200 #ifdef ARCH_32BITS
    201   return (size_t)hash_fnv32(c_str, str_len(str));
    202 #elif defined ARCH_64BITS
    203   return (size_t)hash_fnv64(c_str, str_len(str));
    204 #else
    205   #error "Unexpected architecture"
    206 #endif
    207 }
    208 
    209 #endif /* STR_H */