1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-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 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #include "sfhdr.h" 23 24 /* Read a record delineated by a character. 25 ** The record length can be accessed via sfvalue(f). 26 ** 27 ** Written by Kiem-Phong Vo 28 */ 29 30 #if __STD_C 31 char* sfgetr(reg Sfio_t *f, reg int rc, int type) 32 #else 33 char* sfgetr(f,rc,type) 34 reg Sfio_t* f; /* stream to read from */ 35 reg int rc; /* record separator */ 36 int type; 37 #endif 38 { 39 reg ssize_t n, un; 40 reg uchar *s, *ends, *us; 41 reg int found; 42 reg Sfrsrv_t* rsrv; 43 44 SFMTXSTART(f, NIL(char*)); 45 46 if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) ) 47 SFMTXRETURN(f, NIL(char*)); 48 SFLOCK(f,0); 49 50 /* buffer to be returned */ 51 rsrv = NIL(Sfrsrv_t*); 52 us = NIL(uchar*); 53 un = 0; 54 found = 0; 55 56 /* compatibility mode */ 57 type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type; 58 59 if(type&SF_LASTR) /* return the broken record */ 60 { if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0) 61 { us = rsrv->data; 62 found = 1; 63 } 64 goto done; 65 } 66 67 while(!found) 68 { /* fill buffer if necessary */ 69 if((n = (ends = f->endb) - (s = f->next)) <= 0) 70 { /* for unseekable devices, peek-read 1 record */ 71 f->getr = rc; 72 f->mode |= SF_RC; 73 74 /* fill buffer the conventional way */ 75 if(SFRPEEK(f,s,n) <= 0) 76 { us = NIL(uchar*); 77 goto done; 78 } 79 else 80 { ends = s+n; 81 if(f->mode&SF_RC) 82 { s = ends[-1] == rc ? ends-1 : ends; 83 goto do_copy; 84 } 85 } 86 } 87 88 #if _lib_memchr 89 if(!(s = (uchar*)memchr((char*)s,rc,n))) 90 s = ends; 91 #else 92 while(*s != rc) 93 if((s += 1) == ends) 94 break; 95 #endif 96 do_copy: 97 if(s < ends) /* found separator */ 98 { s += 1; /* include the separator */ 99 found = 1; 100 101 if(!us && 102 (!(type&SF_STRING) || !(f->flags&SF_STRING) || 103 ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) ) 104 { /* returning data in buffer */ 105 us = f->next; 106 un = s - f->next; 107 f->next = s; 108 goto done; 109 } 110 } 111 112 /* amount to be read */ 113 n = s - f->next; 114 115 if(!found && _Sfmaxr > 0 && un+n+1 >= _Sfmaxr) /* already exceed limit */ 116 { us = NIL(uchar*); 117 goto done; 118 } 119 120 /* get internal buffer */ 121 if(!rsrv || rsrv->size < un+n+1) 122 { if(rsrv) 123 rsrv->slen = un; 124 if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*)) 125 us = rsrv->data; 126 else 127 { us = NIL(uchar*); 128 goto done; 129 } 130 } 131 132 /* now copy data */ 133 s = us+un; 134 un += n; 135 ends = f->next; 136 f->next += n; 137 MEMCPY(s,ends,n); 138 } 139 140 done: 141 _Sfi = f->val = un; 142 f->getr = 0; 143 if(found && rc != 0 && (type&SF_STRING) ) 144 { us[un-1] = '\0'; 145 if(us >= f->data && us < f->endb) 146 { f->getr = rc; 147 f->mode |= SF_GETR; 148 } 149 } 150 151 /* prepare for a call to get the broken record */ 152 if(rsrv) 153 rsrv->slen = found ? 0 : -un; 154 155 SFOPEN(f,0); 156 157 if(us && (type&SF_LOCKR) ) 158 { f->mode |= SF_PEEK|SF_GETR; 159 f->endr = f->data; 160 } 161 162 SFMTXRETURN(f, (char*)us); 163 } 164