-
Notifications
You must be signed in to change notification settings - Fork 0
/
str.h
87 lines (77 loc) · 2.74 KB
/
str.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//
// Immutable, not necessarily null-terminated strings
//
typedef struct {
const char *head;
const int len;
} str;
str str_new(const char *s) {
return (str) { .head = s, .len = strlen(s) };
}
str str_new_s(const char *s, const int len) {
return (str) { .head = s, .len = len };
}
int str_ncmp(const str lhs, const str rhs, const int count) {
// TODO bounds check `count`
return strncmp(lhs.head, rhs.head, count);
}
str str_slice(const str s, const int from, const int to) {
// TODO bounds check `from` and `to`
// TODO handle negative `from` (count from end)
// TODO handle negative `to` (count from end)
return (str) { .head = s.head+from, .len = to-from };
}
char *str_to_char(const str s) {
static char str_to_char_buffer[65536];
static char *cursor = str_to_char_buffer;
char *dest = strncpy(cursor, s.head, s.len);
cursor[s.len] = '\0';
cursor += s.len + 2;
return dest;
}
void str_pp(const str s) {
printf("[str %p:%d] \"%.*s\"\n", (void *) s.head, s.len, s.len, s.head);
}
// struct {
// char **head;
// } string
//
// string string_new(const char s*) {
// return (string) {
//
// }
//
//
// Adapt arr.h for strings.
// - handle null-terminator
// - e.g. str_concat(a, "abc") does something like: strcpy(arr_add(a, strlen(s)), s)
// - maybe combine with `struct str` and have `head` be a pointer to a pointer?
// - other stuff?
//
// #define arr_add(a, n) (_arr_maybe_grow(a,n), _arr_len(a)+=(n), &(a)[_arr_len(a)-(n)])
// #define arr_append(a, v) (_arr_maybe_grow((a),1), (a)[_arr_len(a)++]=(v))
// #define arr_capacity(a) ((a) ? _arr_cap(a) : 0)
// #define arr_count(a) ((a) ? _arr_len(a) : 0)
// #define arr_free(a) ((a) ? free(_arr_raw(a)), 0 : 0)
// #define arr_last(a) ((a)[_arr_len(a)-1])
// #define arr_reserve(a, n) (_arr_grow((a,n), _arr_cap(a)+=(n), &(a)[_arr_cap(a)-(n)])
// #define _arr_raw(a) ((int *)(a)-2)
// #define _arr_cap(a) _arr_raw(a)[0]
// #define _arr_len(a) _arr_raw(a)[1]
// #define _arr_need_grow(a, n) ((a)==0 || _arr_len(a)+(n) >= _arr_cap(a))
// #define _arr_maybe_grow(a, n) (_arr_need_grow(a,(n)) ? _arr_grow(a,n) : 0)
// #define _arr_grow(a, n) (*((void **)&(a)) = _arr_growf((a), (n), sizeof(*(a))))
// static void *_arr_growf(void *arr, int increment, int item_size)
// {
// int dbl_cap = arr ? 2 * _arr_cap(arr) : 0;
// int min_cap = arr_count(arr) + increment;
// int new_cap = dbl_cap > min_cap ? dbl_cap : min_cap;
// int *p = (int *) realloc(arr ? _arr_raw(arr) : 0, item_size * new_cap + 2 * sizeof(int));
// if (p) {
// if (!arr) { p[1] = 0; }
// p[0] = new_cap;
// return p+2;
// } else {
// return (void *) (2 * sizeof(int)); // try to force a NULL pointer exception later
// }
// }