xref: /minix3/crypto/external/bsd/netpgp/dist/src/lib/bufgap.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc /* $NetBSD: bufgap.c,v 1.5 2010/11/29 06:21:40 agc Exp $ */
2*ebfedea0SLionel Sambuc 
3*ebfedea0SLionel Sambuc /*-
4*ebfedea0SLionel Sambuc  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
5*ebfedea0SLionel Sambuc  * All rights reserved.
6*ebfedea0SLionel Sambuc  *
7*ebfedea0SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
8*ebfedea0SLionel Sambuc  * by Alistair Crooks (agc@NetBSD.org)
9*ebfedea0SLionel Sambuc  *
10*ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11*ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
12*ebfedea0SLionel Sambuc  * are met:
13*ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15*ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17*ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18*ebfedea0SLionel Sambuc  *
19*ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*ebfedea0SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*ebfedea0SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*ebfedea0SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*ebfedea0SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*ebfedea0SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*ebfedea0SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*ebfedea0SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*ebfedea0SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*ebfedea0SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*ebfedea0SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
30*ebfedea0SLionel Sambuc  */
31*ebfedea0SLionel Sambuc #include "config.h"
32*ebfedea0SLionel Sambuc 
33*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_TYPES_H
34*ebfedea0SLionel Sambuc #include <sys/types.h>
35*ebfedea0SLionel Sambuc #endif
36*ebfedea0SLionel Sambuc 
37*ebfedea0SLionel Sambuc #ifdef HAVE_SYS_STAT_H
38*ebfedea0SLionel Sambuc #include <sys/stat.h>
39*ebfedea0SLionel Sambuc #endif
40*ebfedea0SLionel Sambuc 
41*ebfedea0SLionel Sambuc #include <ctype.h>
42*ebfedea0SLionel Sambuc #include <stdio.h>
43*ebfedea0SLionel Sambuc #include <stdlib.h>
44*ebfedea0SLionel Sambuc 
45*ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H
46*ebfedea0SLionel Sambuc #include <unistd.h>
47*ebfedea0SLionel Sambuc #endif
48*ebfedea0SLionel Sambuc 
49*ebfedea0SLionel Sambuc #ifdef HAVE_STRING_H
50*ebfedea0SLionel Sambuc #include <string.h>
51*ebfedea0SLionel Sambuc #endif
52*ebfedea0SLionel Sambuc 
53*ebfedea0SLionel Sambuc #include "bufgap.h"
54*ebfedea0SLionel Sambuc #include "defs.h"
55*ebfedea0SLionel Sambuc 
56*ebfedea0SLionel Sambuc /* macros to get subscripts in buffer */
57*ebfedea0SLionel Sambuc #define AFTSUB(bp, n)	((bp)->buf[(int)n])
58*ebfedea0SLionel Sambuc #define BEFSUB(bp, n)	((bp)->buf[(int)((bp)->size - (n) - 1)])
59*ebfedea0SLionel Sambuc 
60*ebfedea0SLionel Sambuc /* initial allocation size */
61*ebfedea0SLionel Sambuc #ifndef CHUNKSIZE
62*ebfedea0SLionel Sambuc #define CHUNKSIZE	256
63*ebfedea0SLionel Sambuc #endif
64*ebfedea0SLionel Sambuc 
65*ebfedea0SLionel Sambuc #ifndef KiB
66*ebfedea0SLionel Sambuc #define KiB(x)	((x) * 1024)
67*ebfedea0SLionel Sambuc #endif
68*ebfedea0SLionel Sambuc 
69*ebfedea0SLionel Sambuc #define BGCHUNKSIZE	KiB(4)
70*ebfedea0SLionel Sambuc 
71*ebfedea0SLionel Sambuc #ifndef __UNCONST
72*ebfedea0SLionel Sambuc #define __UNCONST(a)       ((void *)(unsigned long)(const void *)(a))
73*ebfedea0SLionel Sambuc #endif
74*ebfedea0SLionel Sambuc 
75*ebfedea0SLionel Sambuc #ifndef USE_UTF
76*ebfedea0SLionel Sambuc #define USE_UTF	0
77*ebfedea0SLionel Sambuc #endif
78*ebfedea0SLionel Sambuc 
79*ebfedea0SLionel Sambuc #if !USE_UTF
80*ebfedea0SLionel Sambuc #define Rune		char
81*ebfedea0SLionel Sambuc #define	utfbytes(x)	strlen(x)
82*ebfedea0SLionel Sambuc #define	utfrune(a, b)	strchr(a, b)
83*ebfedea0SLionel Sambuc #define	utfnlen(a, b)	bounded_strlen(a, b)
84*ebfedea0SLionel Sambuc 
85*ebfedea0SLionel Sambuc static size_t
bounded_strlen(const char * s,size_t maxlen)86*ebfedea0SLionel Sambuc bounded_strlen(const char *s, size_t maxlen)
87*ebfedea0SLionel Sambuc {
88*ebfedea0SLionel Sambuc 	size_t	n;
89*ebfedea0SLionel Sambuc 
90*ebfedea0SLionel Sambuc 	for (n = 0 ; n < maxlen && s[n] != 0x0 ; n++) {
91*ebfedea0SLionel Sambuc 	}
92*ebfedea0SLionel Sambuc 	return n;
93*ebfedea0SLionel Sambuc }
94*ebfedea0SLionel Sambuc 
95*ebfedea0SLionel Sambuc static int
chartorune(Rune * rp,char * s)96*ebfedea0SLionel Sambuc chartorune(Rune *rp, char *s)
97*ebfedea0SLionel Sambuc {
98*ebfedea0SLionel Sambuc 	*rp = s[0];
99*ebfedea0SLionel Sambuc 	return 1;
100*ebfedea0SLionel Sambuc }
101*ebfedea0SLionel Sambuc 
102*ebfedea0SLionel Sambuc static int
priorrune(Rune * rp,char * s)103*ebfedea0SLionel Sambuc priorrune(Rune *rp, char *s)
104*ebfedea0SLionel Sambuc {
105*ebfedea0SLionel Sambuc 	*rp = s[0];
106*ebfedea0SLionel Sambuc 	return 1;
107*ebfedea0SLionel Sambuc }
108*ebfedea0SLionel Sambuc #else
109*ebfedea0SLionel Sambuc #include "ure.h"
110*ebfedea0SLionel Sambuc #endif
111*ebfedea0SLionel Sambuc 
112*ebfedea0SLionel Sambuc /* save `n' chars of `s' in malloc'd memory */
113*ebfedea0SLionel Sambuc static char *
strnsave(char * s,int n)114*ebfedea0SLionel Sambuc strnsave(char *s, int n)
115*ebfedea0SLionel Sambuc {
116*ebfedea0SLionel Sambuc 	char	*cp;
117*ebfedea0SLionel Sambuc 
118*ebfedea0SLionel Sambuc 	if (n < 0) {
119*ebfedea0SLionel Sambuc 		n = (int)strlen(s);
120*ebfedea0SLionel Sambuc 	}
121*ebfedea0SLionel Sambuc 	NEWARRAY(char, cp, n + 1, "strnsave", return NULL);
122*ebfedea0SLionel Sambuc 	(void) memcpy(cp, s, (size_t)n);
123*ebfedea0SLionel Sambuc 	cp[n] = 0x0;
124*ebfedea0SLionel Sambuc 	return cp;
125*ebfedea0SLionel Sambuc }
126*ebfedea0SLionel Sambuc 
127*ebfedea0SLionel Sambuc /* open a file in a buffer gap structure */
128*ebfedea0SLionel Sambuc int
bufgap_open(bufgap_t * bp,const char * f)129*ebfedea0SLionel Sambuc bufgap_open(bufgap_t *bp, const char *f)
130*ebfedea0SLionel Sambuc {
131*ebfedea0SLionel Sambuc 	struct stat	 s;
132*ebfedea0SLionel Sambuc 	int64_t		 cc;
133*ebfedea0SLionel Sambuc 	FILE		*filep;
134*ebfedea0SLionel Sambuc 	char		*cp;
135*ebfedea0SLionel Sambuc 
136*ebfedea0SLionel Sambuc 	(void) memset(bp, 0x0, sizeof(*bp));
137*ebfedea0SLionel Sambuc 	filep = NULL;
138*ebfedea0SLionel Sambuc 	if (f != NULL && (filep = fopen(f, "r")) == NULL) {
139*ebfedea0SLionel Sambuc 		return 0;
140*ebfedea0SLionel Sambuc 	}
141*ebfedea0SLionel Sambuc 	if (f == NULL) {
142*ebfedea0SLionel Sambuc 		bp->size = BGCHUNKSIZE;
143*ebfedea0SLionel Sambuc 		NEWARRAY(char, bp->buf, bp->size, "f_open", return 0);
144*ebfedea0SLionel Sambuc 	} else {
145*ebfedea0SLionel Sambuc 		(void) fstat(fileno(filep), &s);
146*ebfedea0SLionel Sambuc 		bp->size = (int) ((s.st_size / BGCHUNKSIZE) + 1) * BGCHUNKSIZE;
147*ebfedea0SLionel Sambuc 		NEWARRAY(char, bp->buf, bp->size, "f_open", return 0);
148*ebfedea0SLionel Sambuc 		cc = fread(&BEFSUB(bp, s.st_size), sizeof(char),
149*ebfedea0SLionel Sambuc 						(size_t)s.st_size, filep);
150*ebfedea0SLionel Sambuc 		(void) fclose(filep);
151*ebfedea0SLionel Sambuc 		if (cc != s.st_size) {
152*ebfedea0SLionel Sambuc 			FREE(bp->buf);
153*ebfedea0SLionel Sambuc 			FREE(bp);
154*ebfedea0SLionel Sambuc 			return 0;
155*ebfedea0SLionel Sambuc 		}
156*ebfedea0SLionel Sambuc 		bp->name = strnsave(__UNCONST(f), (int)utfbytes(__UNCONST(f)));
157*ebfedea0SLionel Sambuc 		bp->bbc = s.st_size;
158*ebfedea0SLionel Sambuc 		cp = &BEFSUB(bp, cc);
159*ebfedea0SLionel Sambuc 		for (;;) {
160*ebfedea0SLionel Sambuc 			if ((cp = utfrune(cp, '\n')) == NULL) {
161*ebfedea0SLionel Sambuc 				break;
162*ebfedea0SLionel Sambuc 			}
163*ebfedea0SLionel Sambuc 			bp->blc++;
164*ebfedea0SLionel Sambuc 			cp++;
165*ebfedea0SLionel Sambuc 		}
166*ebfedea0SLionel Sambuc 		bp->bcc = utfnlen(&BEFSUB(bp, cc), (size_t)cc);
167*ebfedea0SLionel Sambuc 	}
168*ebfedea0SLionel Sambuc 	return 1;
169*ebfedea0SLionel Sambuc }
170*ebfedea0SLionel Sambuc 
171*ebfedea0SLionel Sambuc /* close a buffer gapped file */
172*ebfedea0SLionel Sambuc void
bufgap_close(bufgap_t * bp)173*ebfedea0SLionel Sambuc bufgap_close(bufgap_t *bp)
174*ebfedea0SLionel Sambuc {
175*ebfedea0SLionel Sambuc 	FREE(bp->buf);
176*ebfedea0SLionel Sambuc }
177*ebfedea0SLionel Sambuc 
178*ebfedea0SLionel Sambuc /* move forwards `n' chars/bytes in a buffer gap */
179*ebfedea0SLionel Sambuc int
bufgap_forwards(bufgap_t * bp,uint64_t n,int type)180*ebfedea0SLionel Sambuc bufgap_forwards(bufgap_t *bp, uint64_t n, int type)
181*ebfedea0SLionel Sambuc {
182*ebfedea0SLionel Sambuc 	Rune	r;
183*ebfedea0SLionel Sambuc 	int	rlen;
184*ebfedea0SLionel Sambuc 
185*ebfedea0SLionel Sambuc 	switch(type) {
186*ebfedea0SLionel Sambuc 	case BGChar:
187*ebfedea0SLionel Sambuc 		if (bp->bcc >= n) {
188*ebfedea0SLionel Sambuc 			while (n-- > 0) {
189*ebfedea0SLionel Sambuc 				rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
190*ebfedea0SLionel Sambuc 				if (rlen == 1) {
191*ebfedea0SLionel Sambuc 					AFTSUB(bp, bp->abc) = BEFSUB(bp, bp->bbc);
192*ebfedea0SLionel Sambuc 				} else {
193*ebfedea0SLionel Sambuc 					(void) memmove(&AFTSUB(bp, bp->abc),
194*ebfedea0SLionel Sambuc 							&BEFSUB(bp, bp->bbc),
195*ebfedea0SLionel Sambuc 							(size_t)rlen);
196*ebfedea0SLionel Sambuc 				}
197*ebfedea0SLionel Sambuc 				bp->acc++;
198*ebfedea0SLionel Sambuc 				bp->bcc--;
199*ebfedea0SLionel Sambuc 				bp->abc += rlen;
200*ebfedea0SLionel Sambuc 				bp->bbc -= rlen;
201*ebfedea0SLionel Sambuc 				if (r == '\n') {
202*ebfedea0SLionel Sambuc 					bp->alc++;
203*ebfedea0SLionel Sambuc 					bp->blc--;
204*ebfedea0SLionel Sambuc 				}
205*ebfedea0SLionel Sambuc 			}
206*ebfedea0SLionel Sambuc 			return 1;
207*ebfedea0SLionel Sambuc 		}
208*ebfedea0SLionel Sambuc 		break;
209*ebfedea0SLionel Sambuc 	case BGByte:
210*ebfedea0SLionel Sambuc 		if (bp->bbc >= n) {
211*ebfedea0SLionel Sambuc 			for ( ; n > 0 ; n -= rlen) {
212*ebfedea0SLionel Sambuc 				rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
213*ebfedea0SLionel Sambuc 				if (rlen == 1) {
214*ebfedea0SLionel Sambuc 					AFTSUB(bp, bp->abc) = BEFSUB(bp, bp->bbc);
215*ebfedea0SLionel Sambuc 				} else {
216*ebfedea0SLionel Sambuc 					(void) memmove(&AFTSUB(bp, bp->abc),
217*ebfedea0SLionel Sambuc 							&BEFSUB(bp, bp->bbc),
218*ebfedea0SLionel Sambuc 							(size_t)rlen);
219*ebfedea0SLionel Sambuc 				}
220*ebfedea0SLionel Sambuc 				bp->acc++;
221*ebfedea0SLionel Sambuc 				bp->bcc--;
222*ebfedea0SLionel Sambuc 				bp->abc += rlen;
223*ebfedea0SLionel Sambuc 				bp->bbc -= rlen;
224*ebfedea0SLionel Sambuc 				if (r == '\n') {
225*ebfedea0SLionel Sambuc 					bp->alc++;
226*ebfedea0SLionel Sambuc 					bp->blc--;
227*ebfedea0SLionel Sambuc 				}
228*ebfedea0SLionel Sambuc 			}
229*ebfedea0SLionel Sambuc 			return 1;
230*ebfedea0SLionel Sambuc 		}
231*ebfedea0SLionel Sambuc 	}
232*ebfedea0SLionel Sambuc 	return 0;
233*ebfedea0SLionel Sambuc }
234*ebfedea0SLionel Sambuc 
235*ebfedea0SLionel Sambuc /* move backwards `n' chars in a buffer gap */
236*ebfedea0SLionel Sambuc int
bufgap_backwards(bufgap_t * bp,uint64_t n,int type)237*ebfedea0SLionel Sambuc bufgap_backwards(bufgap_t *bp, uint64_t n, int type)
238*ebfedea0SLionel Sambuc {
239*ebfedea0SLionel Sambuc 	Rune	r;
240*ebfedea0SLionel Sambuc 	int	rlen;
241*ebfedea0SLionel Sambuc 
242*ebfedea0SLionel Sambuc 	switch(type) {
243*ebfedea0SLionel Sambuc 	case BGChar:
244*ebfedea0SLionel Sambuc 		if (bp->acc >= n) {
245*ebfedea0SLionel Sambuc 			while (n-- > 0) {
246*ebfedea0SLionel Sambuc 				rlen = priorrune(&r, &AFTSUB(bp, bp->abc));
247*ebfedea0SLionel Sambuc 				bp->bcc++;
248*ebfedea0SLionel Sambuc 				bp->acc--;
249*ebfedea0SLionel Sambuc 				bp->bbc += rlen;
250*ebfedea0SLionel Sambuc 				bp->abc -= rlen;
251*ebfedea0SLionel Sambuc 				if (rlen == 1) {
252*ebfedea0SLionel Sambuc 					BEFSUB(bp, bp->bbc) = AFTSUB(bp, bp->abc);
253*ebfedea0SLionel Sambuc 				} else {
254*ebfedea0SLionel Sambuc 					(void) memmove(&BEFSUB(bp, bp->bbc),
255*ebfedea0SLionel Sambuc 							&AFTSUB(bp, bp->abc),
256*ebfedea0SLionel Sambuc 							(size_t)rlen);
257*ebfedea0SLionel Sambuc 				}
258*ebfedea0SLionel Sambuc 				if (r == '\n') {
259*ebfedea0SLionel Sambuc 					bp->blc++;
260*ebfedea0SLionel Sambuc 					bp->alc--;
261*ebfedea0SLionel Sambuc 				}
262*ebfedea0SLionel Sambuc 			}
263*ebfedea0SLionel Sambuc 			return 1;
264*ebfedea0SLionel Sambuc 		}
265*ebfedea0SLionel Sambuc 		break;
266*ebfedea0SLionel Sambuc 	case BGByte:
267*ebfedea0SLionel Sambuc 		if (bp->acc >= n) {
268*ebfedea0SLionel Sambuc 			for ( ; n > 0 ; n -= rlen) {
269*ebfedea0SLionel Sambuc 				rlen = priorrune(&r, &AFTSUB(bp, bp->abc));
270*ebfedea0SLionel Sambuc 				bp->bcc++;
271*ebfedea0SLionel Sambuc 				bp->acc--;
272*ebfedea0SLionel Sambuc 				bp->bbc += rlen;
273*ebfedea0SLionel Sambuc 				bp->abc -= rlen;
274*ebfedea0SLionel Sambuc 				if (rlen == 1) {
275*ebfedea0SLionel Sambuc 					BEFSUB(bp, bp->bbc) = AFTSUB(bp, bp->abc);
276*ebfedea0SLionel Sambuc 				} else {
277*ebfedea0SLionel Sambuc 					(void) memmove(&BEFSUB(bp, bp->bbc),
278*ebfedea0SLionel Sambuc 							&AFTSUB(bp, bp->abc),
279*ebfedea0SLionel Sambuc 							(size_t)rlen);
280*ebfedea0SLionel Sambuc 				}
281*ebfedea0SLionel Sambuc 				if (r == '\n') {
282*ebfedea0SLionel Sambuc 					bp->blc++;
283*ebfedea0SLionel Sambuc 					bp->alc--;
284*ebfedea0SLionel Sambuc 				}
285*ebfedea0SLionel Sambuc 			}
286*ebfedea0SLionel Sambuc 			return 1;
287*ebfedea0SLionel Sambuc 		}
288*ebfedea0SLionel Sambuc 	}
289*ebfedea0SLionel Sambuc 	return 0;
290*ebfedea0SLionel Sambuc }
291*ebfedea0SLionel Sambuc 
292*ebfedea0SLionel Sambuc /* move within a buffer gap */
293*ebfedea0SLionel Sambuc int
bufgap_seek(bufgap_t * bp,int64_t off,int whence,int type)294*ebfedea0SLionel Sambuc bufgap_seek(bufgap_t *bp, int64_t off, int whence, int type)
295*ebfedea0SLionel Sambuc {
296*ebfedea0SLionel Sambuc 	switch(type) {
297*ebfedea0SLionel Sambuc 	case BGLine:
298*ebfedea0SLionel Sambuc 		switch(whence) {
299*ebfedea0SLionel Sambuc 		case BGFromBOF:
300*ebfedea0SLionel Sambuc 			if (off < 0 || off > (int64_t)(bp->alc + bp->blc)) {
301*ebfedea0SLionel Sambuc 				return 0;
302*ebfedea0SLionel Sambuc 			}
303*ebfedea0SLionel Sambuc 			if (off < (int64_t)bp->alc) {
304*ebfedea0SLionel Sambuc 				while (off <= (int64_t)bp->alc && bufgap_backwards(bp, 1, BGChar)) {
305*ebfedea0SLionel Sambuc 				}
306*ebfedea0SLionel Sambuc 				if (off > 0) {
307*ebfedea0SLionel Sambuc 					(void) bufgap_forwards(bp, 1, BGChar);
308*ebfedea0SLionel Sambuc 				}
309*ebfedea0SLionel Sambuc 			} else if (off > (int64_t)bp->alc) {
310*ebfedea0SLionel Sambuc 				while (off > (int64_t)bp->alc && bufgap_forwards(bp, 1, BGChar)) {
311*ebfedea0SLionel Sambuc 				}
312*ebfedea0SLionel Sambuc 			}
313*ebfedea0SLionel Sambuc 			return 1;
314*ebfedea0SLionel Sambuc 		case BGFromHere:
315*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->alc + off), BGFromBOF, BGLine);
316*ebfedea0SLionel Sambuc 		case BGFromEOF:
317*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->alc + bp->blc + off), BGFromBOF, BGLine);
318*ebfedea0SLionel Sambuc 		}
319*ebfedea0SLionel Sambuc 		break;
320*ebfedea0SLionel Sambuc 	case BGChar:
321*ebfedea0SLionel Sambuc 		switch(whence) {
322*ebfedea0SLionel Sambuc 		case BGFromBOF:
323*ebfedea0SLionel Sambuc 			if (off < 0 || off > (int64_t)(bp->acc + bp->bcc)) {
324*ebfedea0SLionel Sambuc 				return 0;
325*ebfedea0SLionel Sambuc 			}
326*ebfedea0SLionel Sambuc 			if (off < (int64_t)bp->acc) {
327*ebfedea0SLionel Sambuc 				return bufgap_backwards(bp, bp->acc - off, BGChar);
328*ebfedea0SLionel Sambuc 			} else if (off > (int64_t)bp->acc) {
329*ebfedea0SLionel Sambuc 				return bufgap_forwards(bp, off - bp->acc, BGChar);
330*ebfedea0SLionel Sambuc 			}
331*ebfedea0SLionel Sambuc 			return 1;
332*ebfedea0SLionel Sambuc 		case BGFromHere:
333*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->acc + off), BGFromBOF, BGChar);
334*ebfedea0SLionel Sambuc 		case BGFromEOF:
335*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->acc + bp->bcc + off), BGFromBOF, BGChar);
336*ebfedea0SLionel Sambuc 		}
337*ebfedea0SLionel Sambuc 		break;
338*ebfedea0SLionel Sambuc 	case BGByte:
339*ebfedea0SLionel Sambuc 		switch(whence) {
340*ebfedea0SLionel Sambuc 		case BGFromBOF:
341*ebfedea0SLionel Sambuc 			if (off < 0 || off > (int64_t)(bp->abc + bp->bbc)) {
342*ebfedea0SLionel Sambuc 				return 0;
343*ebfedea0SLionel Sambuc 			}
344*ebfedea0SLionel Sambuc 			if (off < (int64_t)bp->abc) {
345*ebfedea0SLionel Sambuc 				return bufgap_backwards(bp, bp->abc - off, BGByte);
346*ebfedea0SLionel Sambuc 			} else if (off > (int64_t)bp->abc) {
347*ebfedea0SLionel Sambuc 				return bufgap_forwards(bp, off - bp->abc, BGByte);
348*ebfedea0SLionel Sambuc 			}
349*ebfedea0SLionel Sambuc 			return 1;
350*ebfedea0SLionel Sambuc 		case BGFromHere:
351*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->abc + off), BGFromBOF, BGByte);
352*ebfedea0SLionel Sambuc 		case BGFromEOF:
353*ebfedea0SLionel Sambuc 			return bufgap_seek(bp, (int64_t)(bp->abc + bp->bbc + off), BGFromBOF, BGByte);
354*ebfedea0SLionel Sambuc 		}
355*ebfedea0SLionel Sambuc 		break;
356*ebfedea0SLionel Sambuc 	}
357*ebfedea0SLionel Sambuc 	return 0;
358*ebfedea0SLionel Sambuc }
359*ebfedea0SLionel Sambuc 
360*ebfedea0SLionel Sambuc /* return a pointer to the text in the buffer gap */
361*ebfedea0SLionel Sambuc char *
bufgap_getstr(bufgap_t * bp)362*ebfedea0SLionel Sambuc bufgap_getstr(bufgap_t *bp)
363*ebfedea0SLionel Sambuc {
364*ebfedea0SLionel Sambuc 	return &BEFSUB(bp, bp->bbc);
365*ebfedea0SLionel Sambuc }
366*ebfedea0SLionel Sambuc 
367*ebfedea0SLionel Sambuc /* return the binary text in the buffer gap */
368*ebfedea0SLionel Sambuc int
bufgap_getbin(bufgap_t * bp,void * dst,size_t len)369*ebfedea0SLionel Sambuc bufgap_getbin(bufgap_t *bp, void *dst, size_t len)
370*ebfedea0SLionel Sambuc {
371*ebfedea0SLionel Sambuc 	int	cc;
372*ebfedea0SLionel Sambuc 
373*ebfedea0SLionel Sambuc 	cc = (bp->bcc < len) ? (int)bp->bcc : (int)len;
374*ebfedea0SLionel Sambuc 	(void) memcpy(dst, &BEFSUB(bp, bp->bbc), len);
375*ebfedea0SLionel Sambuc 	return cc;
376*ebfedea0SLionel Sambuc }
377*ebfedea0SLionel Sambuc 
378*ebfedea0SLionel Sambuc /* return offset (from beginning/end) in a buffer gap */
379*ebfedea0SLionel Sambuc int64_t
bufgap_tell(bufgap_t * bp,int whence,int type)380*ebfedea0SLionel Sambuc bufgap_tell(bufgap_t *bp, int whence, int type)
381*ebfedea0SLionel Sambuc {
382*ebfedea0SLionel Sambuc 	switch(whence) {
383*ebfedea0SLionel Sambuc 	case BGFromBOF:
384*ebfedea0SLionel Sambuc 		return (type == BGLine) ? bp->alc :
385*ebfedea0SLionel Sambuc 			(type == BGByte) ? bp->abc : bp->acc;
386*ebfedea0SLionel Sambuc 	case BGFromEOF:
387*ebfedea0SLionel Sambuc 		return (type == BGLine) ? bp->blc :
388*ebfedea0SLionel Sambuc 			(type == BGByte) ? bp->bbc : bp->bcc;
389*ebfedea0SLionel Sambuc 	default:
390*ebfedea0SLionel Sambuc 		(void) fprintf(stderr, "weird whence in bufgap_tell\n");
391*ebfedea0SLionel Sambuc 		break;
392*ebfedea0SLionel Sambuc 	}
393*ebfedea0SLionel Sambuc 	return (int64_t)0;
394*ebfedea0SLionel Sambuc }
395*ebfedea0SLionel Sambuc 
396*ebfedea0SLionel Sambuc /* return size of buffer gap */
397*ebfedea0SLionel Sambuc int64_t
bufgap_size(bufgap_t * bp,int type)398*ebfedea0SLionel Sambuc bufgap_size(bufgap_t *bp, int type)
399*ebfedea0SLionel Sambuc {
400*ebfedea0SLionel Sambuc 	return (type == BGLine) ? bp->alc + bp->blc :
401*ebfedea0SLionel Sambuc 		(type == BGChar) ? bp->acc + bp->bcc :
402*ebfedea0SLionel Sambuc 			bp->abc + bp->bbc;
403*ebfedea0SLionel Sambuc }
404*ebfedea0SLionel Sambuc 
405*ebfedea0SLionel Sambuc /* insert `n' chars of `s' in a buffer gap */
406*ebfedea0SLionel Sambuc int
bufgap_insert(bufgap_t * bp,const char * s,int n)407*ebfedea0SLionel Sambuc bufgap_insert(bufgap_t *bp, const char *s, int n)
408*ebfedea0SLionel Sambuc {
409*ebfedea0SLionel Sambuc 	int64_t	off;
410*ebfedea0SLionel Sambuc 	Rune	r;
411*ebfedea0SLionel Sambuc 	int	rlen;
412*ebfedea0SLionel Sambuc 	int	i;
413*ebfedea0SLionel Sambuc 
414*ebfedea0SLionel Sambuc 	if (n < 0) {
415*ebfedea0SLionel Sambuc 		n = (int)strlen(s);
416*ebfedea0SLionel Sambuc 	}
417*ebfedea0SLionel Sambuc 	for (i = 0 ; i < n ; i += rlen) {
418*ebfedea0SLionel Sambuc 		if (bp->bbc + bp->abc == bp->size) {
419*ebfedea0SLionel Sambuc 			off = bufgap_tell(bp, BGFromBOF, BGChar);
420*ebfedea0SLionel Sambuc 			(void) bufgap_seek(bp, 0, BGFromEOF, BGChar);
421*ebfedea0SLionel Sambuc 			bp->size *= 2;
422*ebfedea0SLionel Sambuc 			RENEW(char, bp->buf, bp->size, "bufgap_insert", return 0);
423*ebfedea0SLionel Sambuc 			(void) bufgap_seek(bp, off, BGFromBOF, BGChar);
424*ebfedea0SLionel Sambuc 		}
425*ebfedea0SLionel Sambuc 		if ((rlen = chartorune(&r, __UNCONST(s))) == 1) {
426*ebfedea0SLionel Sambuc 			AFTSUB(bp, bp->abc) = *s;
427*ebfedea0SLionel Sambuc 		} else {
428*ebfedea0SLionel Sambuc 			(void) memmove(&AFTSUB(bp, bp->abc), s, (size_t)rlen);
429*ebfedea0SLionel Sambuc 		}
430*ebfedea0SLionel Sambuc 		if (r == '\n') {
431*ebfedea0SLionel Sambuc 			bp->alc++;
432*ebfedea0SLionel Sambuc 		}
433*ebfedea0SLionel Sambuc 		bp->modified = 1;
434*ebfedea0SLionel Sambuc 		bp->abc += rlen;
435*ebfedea0SLionel Sambuc 		bp->acc++;
436*ebfedea0SLionel Sambuc 		s += rlen;
437*ebfedea0SLionel Sambuc 	}
438*ebfedea0SLionel Sambuc 	return 1;
439*ebfedea0SLionel Sambuc }
440*ebfedea0SLionel Sambuc 
441*ebfedea0SLionel Sambuc /* delete `n' bytes from the buffer gap */
442*ebfedea0SLionel Sambuc int
bufgap_delete(bufgap_t * bp,uint64_t n)443*ebfedea0SLionel Sambuc bufgap_delete(bufgap_t *bp, uint64_t n)
444*ebfedea0SLionel Sambuc {
445*ebfedea0SLionel Sambuc 	uint64_t	i;
446*ebfedea0SLionel Sambuc 	Rune		r;
447*ebfedea0SLionel Sambuc 	int		rlen;
448*ebfedea0SLionel Sambuc 
449*ebfedea0SLionel Sambuc 	if (n <= bp->bbc) {
450*ebfedea0SLionel Sambuc 		for (i = 0 ; i < n ; i += rlen) {
451*ebfedea0SLionel Sambuc 			rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
452*ebfedea0SLionel Sambuc 			if (r == '\n') {
453*ebfedea0SLionel Sambuc 				bp->blc--;
454*ebfedea0SLionel Sambuc 			}
455*ebfedea0SLionel Sambuc 			bp->bbc -= rlen;
456*ebfedea0SLionel Sambuc 			bp->bcc--;
457*ebfedea0SLionel Sambuc 			bp->modified = 1;
458*ebfedea0SLionel Sambuc 		}
459*ebfedea0SLionel Sambuc 		return 1;
460*ebfedea0SLionel Sambuc 	}
461*ebfedea0SLionel Sambuc 	return 0;
462*ebfedea0SLionel Sambuc }
463*ebfedea0SLionel Sambuc 
464*ebfedea0SLionel Sambuc /* look at a character in a buffer gap `delta' UTF chars away */
465*ebfedea0SLionel Sambuc int
bufgap_peek(bufgap_t * bp,int64_t delta)466*ebfedea0SLionel Sambuc bufgap_peek(bufgap_t *bp, int64_t delta)
467*ebfedea0SLionel Sambuc {
468*ebfedea0SLionel Sambuc 	int	ch;
469*ebfedea0SLionel Sambuc 
470*ebfedea0SLionel Sambuc 	if (delta != 0) {
471*ebfedea0SLionel Sambuc 		if (!bufgap_seek(bp, delta, BGFromHere, BGChar)) {
472*ebfedea0SLionel Sambuc 			return -1;
473*ebfedea0SLionel Sambuc 		}
474*ebfedea0SLionel Sambuc 	}
475*ebfedea0SLionel Sambuc 	ch = BEFSUB(bp, bp->bbc);
476*ebfedea0SLionel Sambuc 	if (delta != 0) {
477*ebfedea0SLionel Sambuc 		(void) bufgap_seek(bp, -delta, BGFromHere, BGChar);
478*ebfedea0SLionel Sambuc 	}
479*ebfedea0SLionel Sambuc 	return ch;
480*ebfedea0SLionel Sambuc }
481*ebfedea0SLionel Sambuc 
482*ebfedea0SLionel Sambuc /* return, in malloc'd storage, text from the buffer gap */
483*ebfedea0SLionel Sambuc char *
bufgap_gettext(bufgap_t * bp,int64_t from,int64_t to)484*ebfedea0SLionel Sambuc bufgap_gettext(bufgap_t *bp, int64_t from, int64_t to)
485*ebfedea0SLionel Sambuc {
486*ebfedea0SLionel Sambuc 	int64_t	 off;
487*ebfedea0SLionel Sambuc 	int64_t	 n;
488*ebfedea0SLionel Sambuc 	char	*text;
489*ebfedea0SLionel Sambuc 
490*ebfedea0SLionel Sambuc 	off = bufgap_tell(bp, BGFromBOF, BGChar);
491*ebfedea0SLionel Sambuc 	NEWARRAY(char, text, (to - from + 1), "bufgap_gettext", return NULL);
492*ebfedea0SLionel Sambuc 	(void) bufgap_seek(bp, from, BGFromBOF, BGChar);
493*ebfedea0SLionel Sambuc 	for (n = 0 ; n < to - from ; n++) {
494*ebfedea0SLionel Sambuc 		text[(int)n] = BEFSUB(bp, bp->bbc - n);
495*ebfedea0SLionel Sambuc 	}
496*ebfedea0SLionel Sambuc 	text[(int)n] = 0x0;
497*ebfedea0SLionel Sambuc 	(void) bufgap_seek(bp, off, BGFromBOF, BGChar);
498*ebfedea0SLionel Sambuc 	return text;
499*ebfedea0SLionel Sambuc }
500*ebfedea0SLionel Sambuc 
501*ebfedea0SLionel Sambuc /* return 1 if we wrote the file correctly */
502*ebfedea0SLionel Sambuc int
bufgap_write(bufgap_t * bp,FILE * filep)503*ebfedea0SLionel Sambuc bufgap_write(bufgap_t *bp, FILE *filep)
504*ebfedea0SLionel Sambuc {
505*ebfedea0SLionel Sambuc 	if (fwrite(bp->buf, sizeof(char), (size_t)bp->abc, filep) != (size_t)bp->abc) {
506*ebfedea0SLionel Sambuc 		return 0;
507*ebfedea0SLionel Sambuc 	}
508*ebfedea0SLionel Sambuc 	if (fwrite(&BEFSUB(bp, bp->bbc), sizeof(char), (size_t)bp->bbc, filep) != (size_t)bp->bbc) {
509*ebfedea0SLionel Sambuc 		return 0;
510*ebfedea0SLionel Sambuc 	}
511*ebfedea0SLionel Sambuc 	return 1;
512*ebfedea0SLionel Sambuc }
513*ebfedea0SLionel Sambuc 
514*ebfedea0SLionel Sambuc /* tell if the buffer gap is dirty - has been modified */
515*ebfedea0SLionel Sambuc int
bufgap_dirty(bufgap_t * bp)516*ebfedea0SLionel Sambuc bufgap_dirty(bufgap_t *bp)
517*ebfedea0SLionel Sambuc {
518*ebfedea0SLionel Sambuc 	return (int)bp->modified;
519*ebfedea0SLionel Sambuc }
520