1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 34 Fcin_t _Fcin = {0}; 35 36 /* 37 * open stream <f> for fast character input 38 */ 39 int 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 */ 76 int 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); 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 */ 114 int 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 */ 131 void fcnotify(void (*fun)(Sfio_t*,const char*,int)) 132 { 133 _Fcin.fcfun = fun; 134 } 135 136 #ifdef __EXPORT__ 137 # define extern __EXPORT__ 138 #endif 139 140 #undef fcsave 141 extern void fcsave(Fcin_t *fp) 142 { 143 *fp = _Fcin; 144 } 145 146 #undef fcrestore 147 extern void fcrestore(Fcin_t *fp) 148 { 149 _Fcin = *fp; 150 } 151 152 struct Extra 153 { 154 unsigned char buff[2*MB_LEN_MAX]; 155 unsigned char *next; 156 }; 157 158 int fcmbstate(const char *state, int *s, int *len) 159 { 160 static struct Extra extra; 161 register int i, c, n; 162 if(_Fcin.fcleft) 163 { 164 if((c = mbsize(extra.next)) < 0) 165 c = 1; 166 if((_Fcin.fcleft -= c) <=0) 167 { 168 _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft; 169 _Fcin.fcleft = 0; 170 } 171 *len = c; 172 if(c==1) 173 *s = state[*extra.next++]; 174 else if(c==0) 175 _Fcin.fcleft = 0; 176 else 177 { 178 c = mbchar(extra.next); 179 *s = state['a']; 180 } 181 return(c); 182 } 183 switch(*len = mbsize(_Fcin.fcptr)) 184 { 185 case -1: 186 if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX) 187 { 188 memcmp(extra.buff, _Fcin.fcptr, n); 189 _Fcin.fcptr = _Fcin.fclast; 190 for(i=n; i < MB_LEN_MAX+n; i++) 191 { 192 if((extra.buff[i] = fcgetc(c))==0) 193 break; 194 } 195 _Fcin.fcleft = n; 196 extra.next = extra.buff; 197 return(fcmbstate(state,s,len)); 198 } 199 *len = 1; 200 /* fall through */ 201 case 0: 202 case 1: 203 *s = state[c=fcget()]; 204 break; 205 default: 206 c = mbchar(_Fcin.fcptr); 207 *s = state['a']; 208 } 209 return(c); 210 } 211 212