1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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(Sfio_t *f, int rc, int type) 32 #else 33 char* sfgetr(f,rc,type) 34 Sfio_t* f; /* stream to read from */ 35 int rc; /* record separator */ 36 int type; 37 #endif 38 { 39 ssize_t n, un; 40 uchar *s, *ends, *us; 41 int found; 42 Sfrsrv_t* rsrv; 43 SFMTXDECL(f); /* declare a local stream variable for multithreading */ 44 45 SFMTXENTER(f, NIL(char*)); 46 47 if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) ) 48 SFMTXRETURN(f, NIL(char*)); 49 SFLOCK(f,0); 50 51 /* buffer to be returned */ 52 rsrv = NIL(Sfrsrv_t*); 53 us = NIL(uchar*); 54 un = 0; 55 found = 0; 56 57 /* compatibility mode */ 58 type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type; 59 60 if(type&SF_LASTR) /* return the broken record */ 61 { if((f->flags&SF_STRING) && (un = f->endb - f->next)) 62 { us = f->next; 63 f->next = f->endb; 64 found = 1; 65 } 66 else if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0) 67 { us = rsrv->data; 68 found = 1; 69 } 70 goto done; 71 } 72 73 while(!found) 74 { /* fill buffer if necessary */ 75 if((n = (ends = f->endb) - (s = f->next)) <= 0) 76 { /* for unseekable devices, peek-read 1 record */ 77 f->getr = rc; 78 f->mode |= SF_RC; 79 80 /* fill buffer the conventional way */ 81 if(SFRPEEK(f,s,n) <= 0) 82 { us = NIL(uchar*); 83 goto done; 84 } 85 else 86 { ends = s+n; 87 if(f->mode&SF_RC) 88 { s = ends[-1] == rc ? ends-1 : ends; 89 goto do_copy; 90 } 91 } 92 } 93 94 #if _lib_memchr 95 if(!(s = (uchar*)memchr((char*)s,rc,n))) 96 s = ends; 97 #else 98 while(*s != rc) 99 if((s += 1) == ends) 100 break; 101 #endif 102 do_copy: 103 if(s < ends) /* found separator */ 104 { s += 1; /* include the separator */ 105 found = 1; 106 107 if(!us && 108 (!(type&SF_STRING) || !(f->flags&SF_STRING) || 109 ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) ) 110 { /* returning data in buffer */ 111 us = f->next; 112 un = s - f->next; 113 f->next = s; 114 goto done; 115 } 116 } 117 118 /* amount to be read */ 119 n = s - f->next; 120 121 if(!found && (_Sfmaxr > 0 && un+n+1 >= _Sfmaxr || (f->flags&SF_STRING))) /* already exceed limit */ 122 { us = NIL(uchar*); 123 goto done; 124 } 125 126 /* get internal buffer */ 127 if(!rsrv || rsrv->size < un+n+1) 128 { if(rsrv) 129 rsrv->slen = un; 130 if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*)) 131 us = rsrv->data; 132 else 133 { us = NIL(uchar*); 134 goto done; 135 } 136 } 137 138 /* now copy data */ 139 s = us+un; 140 un += n; 141 ends = f->next; 142 f->next += n; 143 MEMCPY(s,ends,n); 144 } 145 146 done: 147 _Sfi = f->val = un; 148 f->getr = 0; 149 if(found && rc != 0 && (type&SF_STRING) ) 150 { us[un-1] = '\0'; 151 if(us >= f->data && us < f->endb) 152 { f->getr = rc; 153 f->mode |= SF_GETR; 154 } 155 } 156 157 /* prepare for a call to get the broken record */ 158 if(rsrv) 159 rsrv->slen = found ? 0 : -un; 160 161 SFOPEN(f,0); 162 163 if(us && (type&SF_LOCKR) ) 164 { f->mode |= SF_PEEK|SF_GETR; 165 f->endr = f->data; 166 } 167 168 SFMTXRETURN(f, (char*)us); 169 } 170