-
Notifications
You must be signed in to change notification settings - Fork 1
/
abcestring.c
126 lines (120 loc) · 2.6 KB
/
abcestring.c
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
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include "abcerbtree.h"
#include "abcemurmur.h"
#include "abcecontainerof.h"
#include "abcelikely.h"
#include "abceopcodes.h"
#include "abcedatatypes.h"
#include "abcestring.h"
struct abce_strbuf {
char *str;
size_t sz;
size_t cap;
int taint;
};
static void abce_strbuf_bump(struct abce *abce, struct abce_strbuf *buf, size_t bump)
{
char *newbuf;
size_t newcap;
if (buf->taint)
{
return;
}
newcap = buf->sz*2 + 1;
if (newcap < buf->sz + bump)
{
newcap = buf->sz + bump;
}
newbuf = abce->alloc(buf->str, buf->cap, newcap, &abce->alloc_baton);
if (newbuf == NULL)
{
buf->taint = 1;
return;
}
buf->str = newbuf;
buf->cap = newcap;
}
static inline int abce_strbuf_add_nul(struct abce *abce, struct abce_strbuf *buf)
{
if (buf->sz >= buf->cap)
{
abce_strbuf_bump(abce, buf, 1);
if (buf->taint)
{
return -ENOMEM;
}
}
buf->str[buf->sz] = '\0';
return 0;
}
static inline int abce_strbuf_add(struct abce *abce, struct abce_strbuf *buf, char ch)
{
if (buf->sz >= buf->cap)
{
abce_strbuf_bump(abce, buf, 1);
if (buf->taint)
{
return -ENOMEM;
}
}
buf->str[buf->sz++] = ch;
return 0;
}
static inline int abce_strbuf_add_many(struct abce *abce, struct abce_strbuf *buf, const char *st, size_t sz)
{
if (buf->sz + sz > buf->cap)
{
abce_strbuf_bump(abce, buf, sz);
if (buf->taint)
{
return -ENOMEM;
}
}
memcpy(&buf->str[buf->sz], st, sz);
buf->sz += sz;
return 0;
}
int abce_strgsub(struct abce *abce,
char **res, size_t *ressz, size_t *rescap,
const char *haystack, size_t haystacksz,
const char *needle, size_t needlesz,
const char *sub, size_t subsz)
{
struct abce_strbuf buf = {};
size_t haystackpos = 0;
if (needlesz == 0)
{
*res = NULL;
*ressz = 0;
return -EINVAL;
}
while (haystackpos + needlesz <= haystacksz)
{
if (memcmp(&haystack[haystackpos], needle, needlesz) == 0)
{
abce_strbuf_add_many(abce, &buf, sub, subsz);
haystackpos += needlesz;
continue;
}
abce_strbuf_add(abce, &buf, haystack[haystackpos++]);
}
abce_strbuf_add_many(abce, &buf, &haystack[haystackpos], haystacksz - haystackpos);
abce_strbuf_add_nul(abce, &buf);
if (buf.taint)
{
abce->alloc(buf.str, buf.cap, 0, &abce->alloc_baton);
*res = NULL;
*ressz = 0;
*rescap = 0;
return -ENOMEM;
}
*res = buf.str;
*ressz = buf.sz;
*rescap = buf.cap;
return 0;
}