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