From 789169d70d24ff2c1c9804f0149d0508de6dfcfa Mon Sep 17 00:00:00 2001 From: Enrique Date: Mon, 6 Jan 2025 00:50:11 +0100 Subject: First upload --- str/str.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ str/str.h | 111 ++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100755 str/str.c create mode 100755 str/str.h (limited to 'str') diff --git a/str/str.c b/str/str.c new file mode 100755 index 0000000..5c4c56f --- /dev/null +++ b/str/str.c @@ -0,0 +1,227 @@ +#include "str.h" + + +__attribute__ ((optimize(3))) bool charisalpha(char c){ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +__attribute__ ((optimize(3))) bool charisnum(char c){ + return c >= '0' && c <= '9'; +} + +__attribute__ ((optimize(3))) bool charisblank(char c){ + return c == ' ' || c == '\t'; +} + +__attribute__ ((optimize(3))) bool charislinebreak(char c){ + return c == '\n' || c == '\f' || c == '\v'; +} + +__attribute__ ((optimize(3))) bool charisspace(char c){ + switch(c){ + case ' ': case '\t': case '\n': case '\r': case '\f': case '\v': + return true; + default: + return false; + } +} + +char lowerchar(char c){ + if(c >= 'A' && c <= 'Z') c += 32; + return c; +} + +__attribute__ ((optimize(1))) u32 len(const char *s){ + if(s == NULL) return 0; + u32 l = -1; + while(s[++l]); + return l; +} + +u32 lowers(char *s){ + u32 l = -1; + while(s[++l]) s[l] = lowerchar(s[l]); + return l; +} + +struct str str(char *s){ + struct str r = { + .cap = len(s), + .len = r.cap, + .ptr = calloc(r.len+1, sizeof(char)) + }; + if(r.ptr == NULL) r = (struct str){0}; + else memcpy(r.ptr, s, r.len); + return r; +} + +struct str nstr(u32 cap){ + struct str s = { + .cap = cap, + .len = 0, + .ptr = calloc(cap+1, sizeof(char)) + }; + return s; +} + +int resize_str(struct str *s, u32 nsize){ + if(nsize == 0) return 1; + char *nptr = realloc(s->ptr, nsize); + if(nptr == NULL) return 1; + s->ptr = nptr; + s->cap = nsize; + return 0; +} + +struct str dup_str(struct str s){ + // we use len here to account for static strings that have no cap + struct str r = {.cap = s.len, .len = s.len, .ptr = calloc(s.len+1, sizeof(char))}; + if(r.ptr == NULL) return (struct str){0}; + memcpy(r.ptr, s.ptr, s.len); + return r; +} + +u32 lowerstr(struct str s){ + return lowers(s.ptr); +} + +struct str utostr(u64 n, int b){ + struct str s = { + .ptr = calloc(sizeof(n)*8 + 2, sizeof(char)) + }; + if(s.ptr == NULL) return (struct str){0}; + u64 dn = n, p = 1; + while(dn /= b) p *= b; + while(p){ + dn = n/p; + s.ptr[s.len++] = dn > 9 ? 'A'-10+dn : '0'+dn; + n %= p, p /= b; + } + char *nptr = realloc(s.ptr, s.len+1); + if(nptr == NULL){ + free(s.ptr); + return (struct str){0}; + } + s.ptr = nptr; + s.cap = s.len; + return s; +} + +// TODO add support for different bases +u64 strtou(struct str s){ + u64 i = 0, r = 0; + while(charisnum(s.ptr[i])){ + r *= 10; + r += s.ptr[i++] - '0'; + } + return r; +} + +u64 len_nstrs(u64 n, ...){ + u64 s = 0; + va_list vl; + va_start(vl, n); + for(u64 i = 0; i < n; i++) { + struct str t = va_arg(vl, struct str); + s += t.len; + } + va_end(vl); + return s; +} + +void copy_nstrs(struct str dst, u64 n, ...){ + va_list vl; + va_start(vl, n); + for(u64 i = 0; i < n; i++) { + struct str t = va_arg(vl, struct str); + copy_str(dst, t); + } + va_end(vl); +} + +void move_nstrs(struct str dst, u64 n, ...){ + va_list vl; + va_start(vl, n); + for(u64 i = 0; i < n; i++) { + struct str t = va_arg(vl, struct str); + move_str(dst, t); + } + va_end(vl); +} + +struct str read_delim(char *buf, char d){ + u32 i = 0; + while(buf[i] && buf[i] != d) i++; + struct str s = {.cap = i, .len = i, .ptr = calloc(s.cap+1, sizeof(char))}; + if(s.ptr == NULL) return (struct str){0}; + memcpy(s.ptr, buf, i); + return s; +} + +struct str sread_delim(char *buf, char d){ + u32 i = 0; + while(buf[i] && buf[i] != d) i++; + struct str s = {.cap = 0, .len = i, .ptr = buf}; + return s; +} + +struct str read_delim_f(char *buf, bool (*func)(char), bool func_cond){ + u32 i = 0; + while(buf[i] && (func(buf[i]) != func_cond)) i++; + struct str s = {.cap = i, .len = i, .ptr = calloc(s.cap+1, sizeof(char))}; + if(s.ptr == NULL) return (struct str){0}; + memcpy(s.ptr, buf, i); + return s; +} + +struct str sread_delim_f(char *buf, bool (*func)(char), bool func_cond){ + u32 i = 0; + while(buf[i] && (func(buf[i]) != func_cond)) i++; + struct str s = {.cap = 0, .len = i, .ptr = buf}; + return s; +} + +u32 get_line_len(char *buf){ + u32 l = 0; + while(buf[l] != '\0' && buf[l] != '\n') l++; + return l; +} + +void fd_to_str(struct str *s, int fd, u32 len){ + s->ptr = calloc(len+1, sizeof(char)); + if(s->ptr == NULL) return; + for(u32 l = len; l != 0; l -= read(fd, s->ptr+(len-l), l)); + s->cap = len; + s->len = len; +} + +void file_to_str(struct str *s, FILE *fp, u32 len){ + s->ptr = calloc(len+1, sizeof(char)); + if(s->ptr == NULL) return; + for(u32 l = len; l != 0; l -= fread(s->ptr, sizeof(char), len, fp)); + s->cap = len; + s->len = len; +} + +void print_str(struct str s){ + for(u32 i = 0; i < s.len; i++){ + putchar(s.ptr[i]); + } +} + +void free_str(struct str *s){ + if(s->ptr != NULL && s->cap > 0) free(s->ptr); + s->ptr = NULL; + s->cap = 0; + s->len = 0; +} + +char *charinstr(char c, struct str s){ + for(u32 i = 0; i < s.len; i++){ + if(s.ptr[i] == c){ + return s.ptr + i; + } + } + return NULL; +} + diff --git a/str/str.h b/str/str.h new file mode 100755 index 0000000..080a2b8 --- /dev/null +++ b/str/str.h @@ -0,0 +1,111 @@ +#ifndef STR_H +#define STR_H + +#include +#include +#include +#include +#include +#include +#include +#include "types/types.h" + +#define XSTR(S) STR(S) +#define STR(S) #S + + +struct str { + u32 cap; + u32 len; + char *ptr; +}; + + +bool charisalpha(char c); + +bool charisnum(char c); + +bool charisblank(char c); + +bool charislinebreak(char c); + +bool charisspace(char c); + +char lowerchar(char c); + +u32 len(const char *s); + +u32 lowers(char *s); + +struct str str(char *s); + +struct str nstr(u32 cap); + +#define slen(s) (sizeof(s)-1) + +#define sstr(s) ((struct str){.cap = 0, .len = slen(s), .ptr = s}) + +#define snstr(s, n) ((struct str){.cap = 0, .len = n, .ptr = s}) + +int resize_str(struct str *s, u32 nsize); + +struct str dup_str(struct str s); + +u32 lowerstr(struct str s); + +struct str utostr(u64 n, int b); + +u64 strtou(struct str s); + +#define NUMSTRS(...) (sizeof((struct str[]){{0}, ##__VA_ARGS__})/sizeof(struct str)-1) + +u64 len_nstrs(u64 n, ...); + +#define len_strs(...) \ + len_nstrs(NUMSTRS(__VA_ARGS__), __VA_ARGS__) + +#define copy_str(dest, src) \ + if(dest.ptr != NULL && src.ptr != NULL){ \ + memcpy((dest).ptr+(dest).len, (src).ptr, (src).len); \ + (dest).len += (src).len; \ + } + +#define move_str(dest, src) \ + if(dest.ptr != NULL && src.ptr != NULL){ \ + memmove((dest).ptr+(dest).len, (src).ptr, (src).len); \ + (dest).len += (src).len; \ + } + +void copy_nstrs(struct str dst, u64 n, ...); + +void move_nstrs(struct str dst, u64 n, ...); + +#define copy_strs(d, ...) \ + copy_nstrs(d, NUMSTRS(__VA_ARGS__), __VA_ARGS__); \ + (d).len += len_nstrs(NUMSTRS(__VA_ARGS__), __VA_ARGS__) + +#define move_strs(d, ...) \ + move_nstrs(d, NUMSTRS(__VA_ARGS__), __VA_ARGS__); \ + (d).len += len_nstrs(NUMSTRS(__VA_ARGS__), __VA_ARGS__) + +struct str read_delim(char *buf, char d); + +struct str sread_delim(char *buf, char d); + +struct str read_delim_f(char *buf, bool (*func)(char), bool func_cond); + +struct str sread_delim_f(char *buf, bool (*func)(char), bool func_cond); + +u32 get_line_len(char *buf); + +void fd_to_str(struct str *s, int fd, u32 len); + +void file_to_str(struct str *s, FILE *fp, u32 len); + +void print_str(struct str s); + +void free_str(struct str *s); + +char *charinstr(char c, struct str s); // move somewhere relevant + +#endif -- cgit v1.2.3