-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstack_array.c
More file actions
171 lines (146 loc) · 3.89 KB
/
Copy pathstack_array.c
File metadata and controls
171 lines (146 loc) · 3.89 KB
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
167
168
169
170
171
#include "stack_array.h"
#include <stdarg.h>
#include <stdlib.h>
static int sa_vcountf(const char *fmt, va_list args)
{
va_list args_copy;
int needed;
va_copy(args_copy, args);
#if defined(_MSC_VER)
needed = _vscprintf(fmt, args_copy);
#else
needed = vsnprintf(NULL, 0, fmt, args_copy);
#endif
va_end(args_copy);
return needed;
}
void ss_clear(char *str) {
SA_Header *h = sa_hdr(str);
h->len = 0;
str[0] = '\0';
}
void ss_append_n(char *dst, const char *src, size_t n) {
SA_Header *h = sa_hdr(dst);
size_t rem = h->cap - h->len;
if (rem == 0 || n > rem - 1) {
sa_overflow_abort(h->cap);
return;
}
memcpy(dst + h->len, src, n);
h->len += n;
dst[h->len] = '\0';
}
void ss_append(char *dst, const char *src) {
ss_append_n(dst, src, strlen(src));
}
void ss_pushc(char *str, char c) {
SA_Header *h = sa_hdr(str);
size_t rem = h->cap - h->len;
if (rem < 2) {
sa_overflow_abort(h->cap);
return;
}
str[h->len++] = c;
str[h->len] = '\0';
}
static int ss_vappendf_impl(char *dst, const char *fmt, va_list args) {
SA_Header *h = sa_hdr(dst);
int needed = sa_vcountf(fmt, args);
if (needed < 0) {
sa_overflow_abort(h->cap);
return 0;
}
size_t rem = h->cap - h->len;
size_t n = (size_t)needed;
if (rem == 0 || n > rem - 1) {
sa_overflow_abort(h->cap);
return 0;
}
{
va_list args_copy;
va_copy(args_copy, args);
(void)vsnprintf(dst + h->len, h->cap - h->len, fmt, args_copy);
va_end(args_copy);
}
h->len += (size_t)needed;
return 1;
}
static int ss_vsprintf_impl(char *dst, const char *fmt, va_list args) {
SA_Header *h = sa_hdr(dst);
int needed = sa_vcountf(fmt, args);
if (needed < 0) {
sa_overflow_abort(h->cap);
return 0;
}
if (((size_t)needed) >= h->cap) {
sa_overflow_abort(h->cap);
return 0;
}
va_list args_copy;
va_copy(args_copy, args);
(void)vsnprintf(dst, h->cap, fmt, args_copy);
va_end(args_copy);
h->len = (size_t)needed;
return 1;
}
void ss_appendf(char *dst, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
(void)ss_vappendf_impl(dst, fmt, args);
va_end(args);
}
void ss_sprintf(char *dst, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
(void)ss_vsprintf_impl(dst, fmt, args);
va_end(args);
}
static void sa_default_overflow(size_t cap)
{
fprintf(stderr, "stack_array overflow (cap=%zu)\n", cap);
abort();
}
static void sa_default_underflow(void)
{
fprintf(stderr, "stack_array underflow\n");
abort();
}
static void sa_default_invalid(void)
{
fprintf(stderr, "stack_array invalid state (uninitialized (sa_field_init(...) is required) or corrupted)\n");
abort();
}
static sa_error_overflow_fn sa_overflow_handler = sa_default_overflow;
static sa_error_underflow_fn sa_underflow_handler = sa_default_underflow;
static sa_error_invalid_fn sa_invalid_handler = sa_default_invalid;
sa_error_overflow_fn sa_set_overflow_handler(sa_error_overflow_fn handler)
{
sa_error_overflow_fn previous = sa_overflow_handler;
sa_overflow_handler = handler ? handler : sa_default_overflow;
return previous;
}
sa_error_underflow_fn sa_set_underflow_handler(sa_error_underflow_fn handler)
{
sa_error_underflow_fn previous = sa_underflow_handler;
sa_underflow_handler = handler ? handler : sa_default_underflow;
return previous;
}
sa_error_invalid_fn sa_set_invalid_handler(sa_error_invalid_fn handler)
{
sa_error_invalid_fn prev = sa_invalid_handler;
sa_invalid_handler = handler ? handler : sa_default_invalid;
return prev;
}
void sa_invalid_abort(void)
{
/* MUST NOT CONTINUE */
sa_invalid_handler();
}
void sa_overflow_abort(size_t cap)
{
sa_overflow_handler(cap);
}
void sa_underflow_abort(void)
{
sa_underflow_handler();
}