backend

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.deepztream.com/backend
Log | Files | Refs

dlib.h (7041B)


      1 #ifndef DLIB_H
      2 #define DLIB_H 1
      3 
      4 #include <assert.h>
      5 #include <ctype.h>
      6 #include <stdarg.h>
      7 #include <stdio.h>
      8 #include <stdbool.h>
      9 #include <stdint.h>
     10 #include <stdlib.h>
     11 #include <errno.h>
     12 #include <string.h>
     13 #include <unistd.h>
     14 
     15 #define da_append(da, new)\
     16   do {\
     17     if ((da)->capacity <= (da)->count) {\
     18       (da)->capacity = (da)->capacity ? (da)->capacity * 2 : 16;\
     19       (da)->items = realloc((da)->items, sizeof(*(da)->items) * (da)->capacity);\
     20     }\
     21     (da)->items[(da)->count++] = (new);\
     22   } while(0)
     23 
     24 #define da_prepend(da, new)\
     25   do {\
     26     if ((da)->capacity <= (da)->count) {\
     27       (da)->capacity = (da)->capacity ? (da)->capacity * 2 : 16;\
     28       (da)->items = realloc((da)->items, sizeof(*(da)->items) * (da)->capacity);\
     29     }\
     30     memmove((da)->items + 1, (da)->items, sizeof(*(da)->items) * ((da)->count++));\
     31     (da)->items[0] = (new);\
     32   } while(0)
     33 
     34 #define da_reserve(da, len)\
     35   do {\
     36     if ((da)->capacity >= (len)) break;\
     37     (da)->capacity = (len);\
     38     (da)->items = realloc((da)->items, sizeof(*(da)->items) * (len));\
     39   } while(0)
     40 
     41 #define da_delete(da, index)\
     42   do {\
     43     assert(index >= 0 && index < (da)->count);\
     44     (da)->items[index] = (da)->items[--(da)->count];\
     45   } while (0)
     46 
     47 typedef struct {
     48   union {
     49     char *items;
     50     const char *data;
     51   };
     52   union {
     53     ssize_t count;
     54     ssize_t length;
     55   };
     56   ssize_t capacity;
     57 } string_builder;
     58 
     59 typedef struct {
     60   union {
     61     const char *items;
     62     const char *data;
     63   };
     64   union {
     65     ssize_t count;
     66     ssize_t length;
     67   };
     68 } string_view;
     69 
     70 #define sb_append_char da_append
     71 void sb_printf(string_builder *sb, const char *fmt, ...);
     72 void sb_append_cstr(string_builder *sb, const char *cstr);
     73 void sb_append_sv(string_builder *sb, string_view sv);
     74 
     75 void sb_read(string_builder *sb, int fd);
     76 void sb_read_file(string_builder *sb, int fd);
     77 void sb_write(int fd, string_builder sb);
     78 
     79 void sv_write(int fd, string_view sv);
     80 
     81 #define sv_literal(str) ((string_view){.data = (str), .count = (sizeof (str) - 1)})
     82 
     83 string_view sv_from_sb(string_builder sb);
     84 ssize_t sv_find_char(string_view sv, char c);
     85 
     86 string_view sv_chop(string_view sv, ssize_t count, string_view *rest);
     87 string_view sv_chop_delim(string_view sv, char c, string_view *rest);
     88 
     89 string_view sv_getline(string_view *sv);
     90 
     91 string_view sv_trim_left(string_view sv);
     92 string_view sv_trim_right(string_view sv);
     93 string_view sv_trim(string_view sv);
     94 
     95 string_view sv_substring(string_view sv, ssize_t start, ssize_t req_count);
     96 
     97 int sv_compare(string_view sv1, string_view sv2);
     98 bool sv_equal(string_view sv1, string_view sv2);
     99 
    100 
    101 #ifdef DLIB_IMPLEMENTATION
    102 
    103 void
    104 sb_printf(string_builder *sb, const char *fmt, ...) {
    105   va_list args, args_copy;
    106   va_start(args, fmt);
    107   va_copy(args_copy, args);
    108   int len = vsnprintf(NULL, 0, fmt, args_copy) + 1;
    109   ssize_t new_size = sb->count + len;
    110   da_reserve(sb, new_size);
    111   va_end(args_copy);
    112   vsnprintf(sb->items + sb->count, len, fmt, args);
    113   va_end(args);
    114   sb->count = new_size - 1;
    115 }
    116 
    117 void
    118 sb_append_cstr(string_builder *sb, const char *cstr)
    119 {
    120   ssize_t len = strlen(cstr);
    121   da_reserve(sb, sb->count + len);
    122   strcpy(sb->items + sb->count, cstr);
    123   sb->count += len;
    124 }
    125 
    126 void
    127 sb_append_sv(string_builder *sb, string_view sv)
    128 {
    129   da_reserve(sb, sb->count + sv.count);
    130   memcpy(sb->items + sb->count, sv.data, sv.count);
    131   sb->count += sv.count;
    132 }
    133 
    134 void
    135 sb_read(string_builder *sb, int fd)
    136 {
    137   ssize_t read_count;
    138   ssize_t buf_size = 4096;
    139   char *buf = malloc(buf_size);
    140   do {
    141     read_count = read(fd, buf, buf_size);
    142     if (read_count < 0) {
    143       if (errno == EINTR) {
    144         continue;
    145       }
    146       perror(NULL);
    147       exit(1);
    148     }
    149     if (read_count == 0) {
    150       break;
    151     }
    152     sb_append_sv(sb, ((string_view) {.data = buf, .length = read_count}));
    153     if (read_count < buf_size) {
    154       break;
    155     }
    156   } while (1);
    157   free(buf);
    158 }
    159 
    160 void
    161 sb_read_file(string_builder *sb, int fd)
    162 {
    163   ssize_t read_count;
    164   ssize_t buf_size = 4096;
    165   char *buf = malloc(buf_size);
    166   do {
    167     read_count = read(fd, buf, buf_size);
    168     if (read_count < 0) {
    169       if (errno == EINTR) {
    170         continue;
    171       }
    172       perror(NULL);
    173       exit(1);
    174     }
    175     if (read_count == 0) {
    176       break;
    177     }
    178     sb_append_sv(sb, ((string_view) {.data = buf, .length = read_count}));
    179   } while (1);
    180   free(buf);
    181 }
    182 
    183 void
    184 sb_write(int fd, string_builder sb)
    185 {
    186   write(fd, sb.data, sb.length);
    187 }
    188 
    189 /* String view functions */
    190 
    191 void
    192 sv_write(int fd, string_view sv)
    193 {
    194   write(fd, sv.data, sv.count);
    195 }
    196 
    197 string_view
    198 sv_from_sb(string_builder sb)
    199 {
    200   return (string_view) {.data = sb.items, .count = sb.count};
    201 }
    202 
    203 ssize_t
    204 sv_find_char(string_view sv, char c)
    205 {
    206   ssize_t pos = 0;
    207   while (sv.count > pos && sv.data[pos] != c)
    208     pos++;
    209   for (pos = 0; pos < sv.count && sv.data[pos] != c; pos++);
    210   return pos < sv.count ? pos : -1;
    211 }
    212 
    213 string_view
    214 sv_chop_delim(string_view sv, char c, string_view *rest)
    215 {
    216   ssize_t pos = sv_find_char(sv, c);
    217   string_view res = sv;
    218   if (pos > 0) {
    219     res.count = pos;
    220 
    221     rest->count -= pos + 1;
    222     rest->data += pos + 1;
    223   }
    224   return res;
    225 }
    226 
    227 string_view
    228 sv_chop(string_view sv, ssize_t count, string_view *rest)
    229 {
    230   string_view left = {0};
    231   ssize_t lcount, rcount;
    232   if (count > sv.count) {
    233     lcount = sv.count;
    234     rcount = 0;
    235   } else if (-count > sv.count) {
    236     lcount = 0;
    237     rcount = sv.count;
    238   } else if (count < 0) {
    239     lcount = sv.count + count;
    240     rcount = -count;
    241   } else {
    242     lcount = count;
    243     rcount = sv.count - count;
    244   }
    245   left.data = sv.data;
    246   left.count = lcount;
    247   if (rest) {
    248     rest->data = sv.data + lcount;
    249     rest->count = rcount;
    250   }
    251   return left;
    252 }
    253 
    254 string_view
    255 sv_trim_left(string_view sv)
    256 {
    257   while (sv.count && isspace(sv.data[0])) {
    258     sv.count--;
    259     sv.data++;
    260   }
    261   return sv;
    262 }
    263 
    264 string_view
    265 sv_trim_right(string_view sv)
    266 {
    267   while (sv.count && isspace(sv.data[sv.count - 1])) {
    268     sv.count--;
    269   }
    270   return sv;
    271 }
    272 
    273 string_view
    274 sv_trim(string_view sv)
    275 {
    276   return sv_trim_right(sv_trim_left(sv));
    277 }
    278 
    279 string_view
    280 sv_substring(string_view sv, ssize_t start, ssize_t req_count)
    281 {
    282   string_view ss = {0};
    283   if (start >= sv.count) return ss;
    284   ss.count = (req_count < sv.count - start) ? req_count : sv.count - start;
    285   ss.data = sv.data + start;
    286   return ss;
    287 }
    288 
    289 int
    290 sv_compare(string_view sv1, string_view sv2)
    291 {
    292   if (sv1.data == sv2.data && sv1.count == sv2.count) return 0;
    293   signed char diff;
    294   ssize_t pos;
    295   for (pos = 0; pos < sv1.count; pos++) {
    296     if (pos == sv2.count) return 1;
    297     if ((diff = sv1.data[pos] - sv2.data[pos])) return diff;
    298   }
    299   return pos < sv2.count ? -1 : 0;
    300 }
    301 
    302 bool
    303 sv_equal(string_view sv1, string_view sv2)
    304 {
    305   if (sv1.count != sv2.count) return false;
    306   if (sv1.data == sv2.data) return true;
    307   ssize_t pos;
    308   for (pos = 0; pos < sv1.count && sv1.data[pos] == sv2.data[pos]; pos++);
    309   return pos == sv1.count;
    310 }
    311 
    312 string_view
    313 sv_getline(string_view *sv)
    314 {
    315   string_view line = sv_chop_delim(*sv, '\n', sv);
    316   if (line.count && line.data[line.count - 1] == '\r') {
    317     line.count--;
    318   }
    319   return line;
    320 }
    321 
    322 #endif // DLIB_IMPLEMENTATION
    323 
    324 #endif // DLIB_H