-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathstr.c
More file actions
132 lines (110 loc) · 2.91 KB
/
str.c
File metadata and controls
132 lines (110 loc) · 2.91 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
/* str.c -- es string operations ($Revision: 1.1.1.1 $) */
#include "es.h"
#include "gc.h"
#include "print.h"
/* grow -- buffer grow function for str() */
static int str_grow(Format *f, size_t more) {
Buffer *buf = expandbuffer(f->u.p, more);
f->u.p = buf;
f->buf = buf->str + (f->buf - f->bufbegin);
f->bufbegin = buf->str;
f->bufend = buf->str + buf->len;
return 0;
}
/* strv -- print a formatted string into gc space */
static char *sstrv(char *(*seal)(Buffer *), const char *fmt, va_list args) {
Buffer *buf;
Format format;
gcdisable();
buf = openbuffer(0);
format.u.p = buf;
#if NO_VA_LIST_ASSIGN
memcpy(format.args, args, sizeof(va_list));
#else
format.args = args;
#endif
format.buf = buf->str;
format.bufbegin = buf->str;
format.bufend = buf->str + buf->len;
format.grow = str_grow;
format.flushed = 0;
printfmt(&format, fmt);
fmtputc(&format, '\0');
gcenable();
return seal(format.u.p);
}
extern char *strv(const char *fmt, va_list args) {
return sstrv(sealbuffer, fmt, args);
}
/* str -- create a string (in garbage collection space) by printing to it */
extern char *str VARARGS1(const char *, fmt) {
char *s;
va_list args;
VA_START(args, fmt);
s = strv(fmt, args);
va_end(args);
return s;
}
/* pstr -- create a string (in pspace) by printing to it */
extern char *pstr VARARGS1(const char *, fmt) {
char *s;
va_list args;
VA_START(args, fmt);
s = sstrv(psealbuffer, fmt, args);
va_end(args);
return s;
}
#define PRINT_ALLOCSIZE 64
/* mprint_grow -- buffer grow function for mprint() */
static int mprint_grow(Format *format, size_t more) {
char *buf;
size_t len = format->bufend - format->bufbegin + 1;
len = (len >= more)
? len * 2
: ((len + more) + PRINT_ALLOCSIZE) &~ (PRINT_ALLOCSIZE - 1);
buf = erealloc(format->bufbegin, len);
format->buf = buf + (format->buf - format->bufbegin);
format->bufbegin = buf;
format->bufend = buf + len - 1;
return 0;
}
/* mprint -- create a string in ealloc space by printing to it */
extern char *mprint VARARGS1(const char *, fmt) {
Format format;
format.u.n = 1;
VA_START(format.args, fmt);
format.buf = ealloc(PRINT_ALLOCSIZE);
format.bufbegin = format.buf;
format.bufend = format.buf + PRINT_ALLOCSIZE - 1;
format.grow = mprint_grow;
format.flushed = 0;
printfmt(&format, fmt);
*format.buf = '\0';
va_end(format.args);
return format.bufbegin;
}
/*
* StrList -- lists of strings
* to even include these is probably a premature optimization
*/
DefineTag(StrList, static);
extern StrList *mkstrlist(char *str, StrList *next) {
gcdisable();
assert(str != NULL);
Ref(StrList *, list, gcnew(StrList));
list->str = str;
list->next = next;
gcenable();
RefReturn(list);
}
static void *StrListCopy(void *op) {
void *np = gcnew(StrList);
memcpy(np, op, sizeof (StrList));
return np;
}
static size_t StrListScan(void *p) {
StrList *list = p;
list->str = forward(list->str);
list->next = forward(list->next);
return sizeof (StrList);
}