1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#include <ast.h>
23#include <stdarg.h>
24
25#define STR		(8*1024)
26
27#define VALID(p,f)	((p=(Sfstr_t*)f)>=&strs[0]&&p<&strs[elementsof(strs)])
28
29static Sfstr_t		strs[64];
30
31static int
32extend(Sfstr_t* p, int n)
33{
34	int	o;
35
36	if (n < STR)
37		n = STR;
38	n += p->end - p->beg;
39	o = p->nxt - p->beg;
40	if (!(p->beg = realloc(p->beg, n)))
41		return -1;
42	p->nxt = p->beg + o;
43	p->end = p->beg + n;
44	return 0;
45}
46
47int
48sfclose(Sfio_t* f)
49{
50	Sfstr_t*	p;
51	int		r;
52
53	if (VALID(p, f))
54	{
55		p->nxt = 0;
56		r = 0;
57	}
58	else
59		r = fclose(f);
60	return r;
61}
62
63int
64sfprintf(Sfio_t* f, const char* fmt, ...)
65{
66	Sfstr_t*	p;
67	char*		s;
68	va_list		ap;
69	int		r;
70
71	static char	buf[STR];
72
73	va_start(ap, fmt);
74	if (!VALID(p, f))
75		r = vfprintf(f, fmt, ap);
76	else if ((r = vsnprintf(buf, sizeof(buf), fmt, ap)) > 0)
77		r = sfwrite(f, buf, r);
78	va_end(ap);
79	return r;
80}
81
82char*
83sfprints(const char* fmt, ...)
84{
85	va_list		ap;
86	int		r;
87
88	static char	buf[STR];
89
90	va_start(ap, fmt);
91	r = vsnprintf(buf, sizeof(buf), fmt, ap);
92	va_end(ap);
93	return r > 0 ? buf : (char*)0;
94}
95
96int
97sfputc(Sfio_t* f, int c)
98{
99	Sfstr_t*	p;
100	int		r;
101
102	if (VALID(p, f))
103	{
104		if (p->nxt >= p->end && extend(p, 1))
105			return -1;
106		*p->nxt++ = c;
107		r = 1;
108	}
109	else
110		r = fputc(c, f);
111	return r;
112}
113
114int
115sfputr(Sfio_t* f, const char* buf, int sep)
116{
117	Sfstr_t*	p;
118	int		r;
119	int		n;
120
121	n = strlen(buf);
122	if (VALID(p, f))
123	{
124		r = n + (sep >= 0);
125		if (r > (p->end - p->nxt) && extend(p, r))
126			return -1;
127		memcpy(p->nxt, buf, n);
128		p->nxt += n;
129		if (sep >= 0)
130			*p->nxt++ = sep;
131	}
132	else
133	{
134		r = fwrite(buf, 1, n, f);
135		if (sep >= 0 && fputc(sep, f) != EOF)
136			r++;
137	}
138	return r;
139}
140
141char*
142sfstrbase(Sfio_t* f)
143{
144	Sfstr_t*	p;
145
146	if (VALID(p, f))
147		return p->beg;
148	return 0;
149}
150
151Sfio_t*
152sfstropen(void)
153{
154	Sfstr_t*	p;
155
156	for (p = &strs[0]; p < &strs[elementsof(strs)]; p++)
157		if (!p->nxt)
158		{
159			if (!p->beg)
160			{
161				if (!(p->beg = malloc(STR)))
162					break;
163				p->end = p->beg + STR;
164			}
165			p->nxt = p->beg;
166			return (Sfio_t*)p;
167		}
168	return 0;
169}
170
171#define _sf_strseek(f,p,m) \
172	( (m) == SEEK_SET ? \
173	 	(((p) < 0 || (p) > ((f)->end - (f)->beg)) ? (char*)0 : \
174		 (char*)((f)->nxt = (f)->beg+(p)) ) \
175	: (m) == SEEK_CUR ? \
176		((f)->nxt += (p), \
177		 (((f)->nxt < (f)->beg || (f)->nxt > (f)->end) ? \
178			((f)->nxt -= (p), (char*)0) : (char*)(f)->nxt ) ) \
179	: (m) == SEEK_END ? \
180		( ((p) > 0 || (((f)->end - (f)->beg) + (p)) < 0) ? (char*)0 : \
181			(char*)((f)->nxt = (f)->end+(p)) ) \
182	: (char*)0 \
183	)
184
185char*
186sfstrseek(Sfio_t* f, int n, int w)
187{
188	Sfstr_t*	p;
189
190	if (VALID(p, f))
191		return _sf_strseek(p, n, w);
192	return 0;
193}
194
195char*
196sfstrset(Sfio_t* f, int n)
197{
198	Sfstr_t*	p;
199
200	if (VALID(p, f) && n >= 0 && n < (p->nxt - p->beg))
201		return p->nxt = p->beg + n;
202	return 0;
203}
204
205int
206sfstrtell(Sfio_t* f)
207{
208	Sfstr_t*	p;
209	int		r;
210
211	if (VALID(p, f) && p->nxt)
212		r = p->nxt - p->beg;
213	else
214		r = -1;
215	return r;
216}
217
218char*
219sfstruse(Sfio_t* f)
220{
221	Sfstr_t*	p;
222
223	if (VALID(p, f) && (p->nxt < p->end || !extend(p, 1)))
224	{
225		*p->nxt = 0;
226		return p->nxt = p->beg;
227	}
228	return 0;
229}
230
231int
232sfwrite(Sfio_t* f, void* buf, int n)
233{
234	Sfstr_t*	p;
235
236	if (VALID(p, f))
237	{
238		if (n > (p->end - p->nxt) && extend(p, n))
239			return -1;
240		memcpy(p->nxt, buf, n);
241		p->nxt += n;
242	}
243	else
244		n = fwrite(buf, 1, n, f);
245	return n;
246}
247