1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1982-2010 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* David Korn <dgk@research.att.com> * 18* * 19***********************************************************************/ 20#pragma prototyped 21/* 22 * Routines to implement fast character input 23 * 24 * David Korn 25 * AT&T Labs 26 * 27 */ 28 29#include <ast.h> 30#include <sfio.h> 31#include <error.h> 32#include <fcin.h> 33 34Fcin_t _Fcin = {0}; 35 36/* 37 * open stream <f> for fast character input 38 */ 39int fcfopen(register Sfio_t* f) 40{ 41 register int n; 42 char *buff; 43 Fcin_t save; 44 errno = 0; 45 _Fcin.fcbuff = _Fcin.fcptr; 46 _Fcin._fcfile = f; 47 fcsave(&save); 48 if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR))) 49 { 50 fcrestore(&save); 51 _Fcin.fcchar = 0; 52 _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar; 53 _Fcin.fclast = 0; 54 _Fcin._fcfile = (Sfio_t*)0; 55 return(EOF); 56 } 57 n = sfvalue(f); 58 fcrestore(&save); 59 sfread(f,buff,0); 60 _Fcin.fcoff = sftell(f);; 61 buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR); 62 _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n; 63 if(sffileno(f) >= 0) 64 *_Fcin.fclast = 0; 65 return(n); 66} 67 68 69/* 70 * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and 71 * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer. 72 * If a notify function has been set, it is called 73 * If last is non-zero, and the stream is a file, 0 is returned when 74 * the previous character is a 0 byte. 75 */ 76int fcfill(void) 77{ 78 register int n; 79 register Sfio_t *f; 80 register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr; 81 if(!(f=fcfile())) 82 { 83 /* see whether pointer has passed null byte */ 84 if(ptr>_Fcin.fcbuff && *--ptr==0) 85 _Fcin.fcptr=ptr; 86 else 87 _Fcin.fcoff = 0; 88 return(0); 89 } 90 if(last) 91 { 92 if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0) 93 return(0); 94 if(_Fcin.fcchar) 95 *last = _Fcin.fcchar; 96 if(ptr > last) 97 _Fcin.fcptr = ptr = last; 98 } 99 if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun) 100 (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context); 101 sfread(f, (char*)_Fcin.fcbuff, n); 102 _Fcin.fcoff +=n; 103 _Fcin._fcfile = 0; 104 if(!last) 105 return(0); 106 else if(fcfopen(f) < 0) 107 return(EOF); 108 return(*_Fcin.fcptr++); 109} 110 111/* 112 * Synchronize and close the current stream 113 */ 114int fcclose(void) 115{ 116 register unsigned char *ptr; 117 if(_Fcin.fclast==0) 118 return(0); 119 if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0) 120 _Fcin.fcptr--; 121 if(_Fcin.fcchar) 122 *_Fcin.fclast = _Fcin.fcchar; 123 _Fcin.fclast = 0; 124 _Fcin.fcleft = 0; 125 return(fcfill()); 126} 127 128/* 129 * Set the notify function that is called for each fcfill() 130 */ 131void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context) 132{ 133 _Fcin.fcfun = fun; 134 _Fcin.context = context; 135} 136 137#ifdef __EXPORT__ 138# define extern __EXPORT__ 139#endif 140 141#undef fcsave 142extern void fcsave(Fcin_t *fp) 143{ 144 *fp = _Fcin; 145} 146 147#undef fcrestore 148extern void fcrestore(Fcin_t *fp) 149{ 150 _Fcin = *fp; 151} 152 153struct Extra 154{ 155 unsigned char buff[2*MB_LEN_MAX]; 156 unsigned char *next; 157}; 158 159int fcmbstate(const char *state, int *s, int *len) 160{ 161 static struct Extra extra; 162 register int i, c, n; 163 if(_Fcin.fcleft) 164 { 165 if((c = mbsize(extra.next)) < 0) 166 c = 1; 167 if((_Fcin.fcleft -= c) <=0) 168 { 169 _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft; 170 _Fcin.fcleft = 0; 171 } 172 *len = c; 173 if(c==1) 174 *s = state[*extra.next++]; 175 else if(c==0) 176 _Fcin.fcleft = 0; 177 else 178 { 179 c = mbchar(extra.next); 180 *s = state['a']; 181 } 182 return(c); 183 } 184 switch(*len = mbsize(_Fcin.fcptr)) 185 { 186 case -1: 187 if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX) 188 { 189 memcpy(extra.buff, _Fcin.fcptr, n); 190 _Fcin.fcptr = _Fcin.fclast; 191 for(i=n; i < MB_LEN_MAX+n; i++) 192 { 193 if((extra.buff[i] = fcgetc(c))==0) 194 break; 195 } 196 _Fcin.fcleft = n; 197 extra.next = extra.buff; 198 return(fcmbstate(state,s,len)); 199 } 200 *len = 1; 201 /* fall through */ 202 case 0: 203 case 1: 204 *s = state[c=fcget()]; 205 break; 206 default: 207 c = mbchar(_Fcin.fcptr); 208 *s = state['a']; 209 } 210 return(c); 211} 212 213