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
|
#include "common.h"
#include "strutil.h"
#include <string.h>
char* strdup_len(const char* src, size_t len)
{
char* ret = malloc(len + 1);
if (ret)
{
memcpy(ret, src, len);
ret[len] = '\0';
}
return ret;
}
static inline bool escaped(char* start, char* cur)
{
return cur > start && cur[-1] == '\\' && !escaped(start, cur - 1);
}
void unescape(char* str)
{
char* end = str + strlen(str);
char* s;
for (s = end - 1; s >= str; s--)
{
if (*s == '\\' && s < end - 1 && !escaped(str, s))
{
end--;
memmove(s, s + 1, end - s);
}
}
*end = '\0';
}
char* escape(const char* str, const char* chars)
{
dynstr_t* d = dynstr_new_str(str);
if (d)
{
if (dynstr_escape(d, chars))
{
return dynstr_done(d);
}
dynstr_free(d);
}
return NULL;
}
bool dynstr_escape(dynstr_t* str, const char* chars)
{
char* s;
for (s = str->data + str->len - 1; s >= str->data; s--)
{
if (*s == '\\' || strchr(chars, *s))
{
size_t pos = s - str->data;
if (!dynstr_appendc(str, '/'))
{
return false;
}
s = str->data + pos;
memmove(s + 1, s, str->len - (pos + 1));
*s = '\\';
}
}
return true;
}
static void free_list(char** list, size_t count)
{
char** l;
for (l = list; count-- > 0; l++)
{
free(*l);
}
free(list);
}
char** split_len(const char* start, const char* end, char delim)
{
char** ret;
size_t count = 0, size = 2;
assert(start && end);
assert(start <= end);
ret = malloc((size + 1) * sizeof(char*));
if (ret)
{
const char* last = start;
for (;;)
{
const char* p;
for (p = last; p < end && *p != delim; p++);
if (count == size)
{
size_t ns = size * 2;
char** tmp = realloc(ret, (ns + 1) * sizeof(char*));
if (!tmp)
{
free_list(ret, count);
return NULL;
}
size = ns;
ret = tmp;
}
ret[count] = strdup_len(last, p - last);
if (!ret[count])
{
free_list(ret, count);
return NULL;
}
count++;
if (p == end)
{
break;
}
last = p + 1;
}
ret[count] = NULL;
}
return ret;
}
|