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 
29 static Sfstr_t		strs[64];
30 
31 static int
extend(Sfstr_t * p,int n)32 extend(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 
47 int
sfclose(Sfio_t * f)48 sfclose(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 
63 int
sfprintf(Sfio_t * f,const char * fmt,...)64 sfprintf(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 
82 char*
sfprints(const char * fmt,...)83 sfprints(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 
96 int
sfputc(Sfio_t * f,int c)97 sfputc(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 
114 int
sfputr(Sfio_t * f,const char * buf,int sep)115 sfputr(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 
141 char*
sfstrbase(Sfio_t * f)142 sfstrbase(Sfio_t* f)
143 {
144 	Sfstr_t*	p;
145 
146 	if (VALID(p, f))
147 		return p->beg;
148 	return 0;
149 }
150 
151 Sfio_t*
sfstropen(void)152 sfstropen(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 
185 char*
sfstrseek(Sfio_t * f,int n,int w)186 sfstrseek(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 
195 char*
sfstrset(Sfio_t * f,int n)196 sfstrset(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 
205 int
sfstrtell(Sfio_t * f)206 sfstrtell(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 
218 char*
sfstruse(Sfio_t * f)219 sfstruse(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 
231 int
sfwrite(Sfio_t * f,void * buf,int n)232 sfwrite(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