summaryrefslogtreecommitdiff
path: root/str
diff options
context:
space:
mode:
Diffstat (limited to 'str')
-rwxr-xr-xstr/str.c227
-rwxr-xr-xstr/str.h111
2 files changed, 338 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#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