xref: /inferno-os/libbio/bgetrune.c (revision 72335078034e3cd7edcb1739556b405a3e1e9bf8)
1 #include	"lib9.h"
2 #include	<bio.h>
3 
4 long
Bgetrune(Biobuf * bp)5 Bgetrune(Biobuf *bp)
6 {
7 	int c, i;
8 	Rune rune;
9 	char str[UTFmax];
10 
11 	c = Bgetc(bp);
12 	if(c < Runeself) {		/* one char */
13 		bp->runesize = 1;
14 		return c;
15 	}
16 	str[0] = c;
17 	bp->runesize = 0;
18 
19 	for(i=1;;) {
20 		c = Bgetc(bp);
21 		if(c < 0)
22 			return c;
23 		if (i >= sizeof str)
24 			return Runeerror;
25 		str[i++] = c;
26 
27 		if(fullrune(str, i)) {
28 			/* utf is long enough to be a rune, but could be bad. */
29 			bp->runesize = chartorune(&rune, str);
30 			if (rune == Runeerror)
31 				bp->runesize = 0;	/* push back nothing */
32 			else
33 				/* push back bytes unconsumed by chartorune */
34 				for(; i > bp->runesize; i--)
35 					Bungetc(bp);
36 			return rune;
37 		}
38 	}
39 }
40 
41 int
Bungetrune(Biobuf * bp)42 Bungetrune(Biobuf *bp)
43 {
44 
45 	if(bp->state == Bracteof)
46 		bp->state = Bractive;
47 	if(bp->state != Bractive)
48 		return Beof;
49 	bp->icount -= bp->runesize;
50 	bp->runesize = 0;
51 	return 1;
52 }
53