#ifndef STR_H #define STR_H #include #include #include "typ.h" #include "arena.h" typedef struct { char *s; isize n; } Str; #define S(s) (Str){s,sizeof(s)-1} /* allocating */ Str str_dup(Str a, Arena *m) { char *s = new_arr(m, char, a.n); memcpy(s, a.s, a.n); a.s = s; return a; } static inline void str_cat(Str *a, Str b, Arena *m) { a->s = resize(m, a->s, a->n, a->n + b.n); memcpy(&a->s[a->n], b.s, b.n); a->n += b.n; } /* conversions */ static inline char *str_to_cstr(Str s, Arena *a) { char *r = new_arr(a, char, s.n + 1); memcpy(r, s.s, s.n); r[s.n] = 0; return r; } static inline Str str_from_cstr(const char *s) { return (Str) { (char*)s, strlen(s) }; } /* pure functions */ static inline int str_eql(Str a, Str b) { return a.n == b.n && !memcmp(a.s, b.s, b.n); } static inline int str_starts(Str a, Str b) { return a.n >= b.n && !memcmp(a.s, b.s, b.n); } static inline int str_ends(Str a, Str b) { return a.n >= b.n && !memcmp(&a.s[a.n - b.n], b.s, b.n); } static inline void str_catc(Str *a, char b, Arena *m) { a->s = resize(m, a->s, a->n, a->n + 1); a->s[a->n++] = b; } static inline Str str_skip(Str a, isize n) { return (Str) { a.s + n, a.n - n }; } static inline int is_space(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } static inline Str str_trim_left(Str a) { while (a.n > 0 && is_space(a.s[0])) a.s++, a.n--; return a; } static inline Str str_trim_right(Str a) { while (a.n > 0 && is_space(a.s[a.n - 1])) a.n--; return a; } static inline Str str_trim(Str a) { return str_trim_left(str_trim_right(a)); } typedef struct { Str head, tail; } Cut; static inline Cut str_cut(Str s, char c) { char *p = memchr(s.s, c, s.n); if (!p) { return (Cut) { s, { &s.s[s.n], 0 } }; } else { return (Cut) { { s.s, p - s.s }, { p + 1, &s.s[s.n] - (p + 1) } }; } } #endif