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