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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#pragma once
#include "common.h"
#include "smrt_arena.h"
#define STRNG_BASE_POS (sizeof(strng_t))
typedef struct {
u64 alloc_size;
u64 len;
} strng_t;
typedef struct {
u64 start;
u64 end;
u64 max;
char const *string;
} strng_view_t;
strng_t * strng_new(smrt_arena_t *arena, u64 size);
strng_t * strng_from(smrt_arena_t *arena, char const *c);
strng_t *strng_from_sv(smrt_arena_t *arena, strng_view_t const *sv);
strng_t * strng_dup(smrt_arena_t *arena, strng_t const *src);
char * strng_str(smrt_arena_t *arena, strng_t const *string);
i32 strng_set(strng_t *string, char const *c);
i32 strng_set_ic(strng_t *string, u64 i, char c);
// Append to strng, returns -1 if no space, new len otherwise
i32 strng_app(strng_t *dest, strng_t const *source);
// Append char* to strng, returns -1 if no space, new len otherwise
i32 strng_app_c(strng_t *dest, char const *source);
// Append sv to strng, returns -1 if no space, new len otherwise
i32 strng_app_v(strng_t *dest, strng_view_t const *source);
void strng_clear(strng_t *string);
char *strng_malloc_str(strng_t const *string);
// Applies F to each char in string and updates the value
void strng_map(strng_t *string, char (F)(char c));
typedef b32 (*string_validation_func)(char c) ;
// Runs *validation on each char in the string and returns true if all checks return true. If string.len == 0, returns true.
b32 strng_validate(strng_t const *string, string_validation_func validation);
#define STRNG_TO(s) (char *)((u8*)(s)+STRNG_BASE_POS)
#define STRNG_FMT(s) (i32)(s)->len, (char *)(((u8*)(s))+STRNG_BASE_POS)
#define STRNG_MAPKEY(s) (u8*)STRNG_TO((s)), (s)->len
#define SV_TO(sv) (char *)((u8*)((sv).string) + (sv).start)
#define SV_FMT(sv) (i32)(sv_len(&(sv))), SV_TO((sv))
#define SV_MAPKEY(sv) (u8*)SV_TO((sv)), sv_len(&(sv))
static inline strng_view_t sv_from(strng_t const *string) {
return (strng_view_t){
.string=(char*)((u8*)string+STRNG_BASE_POS),
.start=0,
.end=string->len-1,
.max=string->len-1,
};
}
static inline u64 sv_len(strng_view_t const *sv) {
return (sv->start <= sv->end) ? (sv->end - sv->start + 1) : 0;
}
static inline strng_view_t sv_dup(strng_view_t const *src) { return *src; }
static inline strng_view_t sv_orig(strng_view_t const *src) { return (strng_view_t){
.string=src->string,
.start=0,
.end=src->max,
.max=src->max }; }
static inline strng_view_t sv_subv(strng_view_t const *src,
u64 start_off, u64 max_len) {
u64 src_len = sv_len(src);
u64 new_start = src->start + MIN(start_off, src_len);
u64 available_len = (src->start + src_len) - new_start;
u64 actual_len = MIN(available_len, max_len);
return (strng_view_t){
.string = src->string,
.start = new_start,
.end = actual_len == 0 ? new_start - 1 : new_start + actual_len - 1,
.max = src->max
};
}
static inline strng_view_t sv_drop_left(strng_view_t const *src, u64 n) {
u64 src_len = sv_len(src);
u64 m = MIN(src_len, n);
return sv_subv(src, m, src_len - m);
}
static inline strng_view_t sv_drop_right(strng_view_t const *src, u64 n) {
u64 src_len = sv_len(src);
u64 m = MIN(src_len, n);
return sv_subv(src, 0, src_len - m);
}
strng_view_t sv_from_chars(char const* c);
void sv_trimws_left (strng_view_t *sv);
void sv_trimws_right(strng_view_t *sv);
void sv_trimws (strng_view_t *sv);
void sv_trim_pastc_left (strng_view_t *sv, char n);
void sv_trim_pastc_right(strng_view_t *sv, char n);
// Starts from start and sets end to the next char n.
// Does nothing if there is no next char n
void sv_trim_end_nextc(strng_view_t *sv, char n);
// Starts from end and sets start to the prev char n.
// Does nothing if there is no prev char n
void sv_trim_strt_prvc(strng_view_t *sv, char n);
// Goes backwards from end until character n (skipping n `skip` times)
// and returns the distance from end
u64 sv_find_from_end_c(strng_view_t const *sv, char n, u64 skip);
// Sets length keeping start
void sv_set_len_left (strng_view_t *sv, u64 n);
// Sets length keeping end
void sv_set_len_right(strng_view_t *sv, u64 n);
#define sv_pop_start(sv) sv_pop_left(sv)
#define sv_pop_end(sv) sv_pop_right(sv)
static inline void sv_pop_left (strng_view_t *sv) { if (sv->start <= sv->end) sv->start++; }
static inline void sv_pop_right(strng_view_t *sv) { if (sv->end >= sv->start) sv->end--; }
static inline void sv_popn_left (strng_view_t *sv, u64 n) { for (u64 i = 0; i < n; i++) sv_pop_left(sv); }
static inline void sv_popn_right(strng_view_t *sv, u64 n) { for (u64 i = 0; i < n; i++) sv_pop_right(sv); }
u64 sv_read_n(strng_view_t *sv, char *buf, u64 n);
char sv_get_start(strng_view_t const *sv);
char sv_get_end(strng_view_t const *sv);
static inline void sv_reset(strng_view_t *sv) { sv->start = 0;
sv->end = sv->max; }
static inline void sv_reset_right(strng_view_t *sv) { sv->end = sv->max; }
static inline void sv_reset_left(strng_view_t *sv) { sv->start = 0; }
// Returns -1 if not found, otherwise distance from sv->start to beginning of needle
i32 sv_find_substr(strng_view_t const *sv, char const *needle);
// Returns -1 if not found, otherwise distance from sv->start
i32 sv_find_char(strng_view_t const *sv, char n);
// Count occurrences of n in sv.
u64 sv_count_c(strng_view_t const *sv, char n);
b32 sv_starts_with(strng_view_t const *sv, char const *prefix);
b32 sv_ends_with(strng_view_t const *sv, char const *suffix);
static inline b32 sv_starts_with_c(strng_view_t const *sv, char c) { return
(sv_len(sv) > 0) && (*SV_TO(*sv) == c); }
static inline b32 sv_ends_with_c(strng_view_t const *sv, char c) { return
(sv_len(sv) > 0) && (*(sv->string + sv->end) == c); }
b32 sv_eq_case_insensitive(strng_view_t const *sv1, strng_view_t const *sv2);
// Runs *validation on each char in the sv and returns true if all checks return true. If sv_len(sv) == 0, returns true.
b32 sv_validate(strng_view_t const *sv, string_validation_func validation);
strng_view_t sv_split_once(strng_view_t *sv, char const *needle);
strng_view_t sv_split_once_c(strng_view_t *sv, char n);
// Returns chars read on succes, -1 if couldn't read
// Creates its own SV and skips whitespace.
// Fails if first char after trim isnt +/- or 0-9
i32 sv_to_i64(strng_view_t const *sv, i64 *value_o);
|