1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #include "sfhdr.h"
23da2e3ebdSchin
24da2e3ebdSchin /* Read a record delineated by a character.
25da2e3ebdSchin ** The record length can be accessed via sfvalue(f).
26da2e3ebdSchin **
27da2e3ebdSchin ** Written by Kiem-Phong Vo
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #if __STD_C
sfgetr(Sfio_t * f,int rc,int type)317c2fbfb3SApril Chin char* sfgetr(Sfio_t *f, int rc, int type)
32da2e3ebdSchin #else
33da2e3ebdSchin char* sfgetr(f,rc,type)
347c2fbfb3SApril Chin Sfio_t* f; /* stream to read from */
357c2fbfb3SApril Chin int rc; /* record separator */
36da2e3ebdSchin int type;
37da2e3ebdSchin #endif
38da2e3ebdSchin {
397c2fbfb3SApril Chin ssize_t n, un;
407c2fbfb3SApril Chin uchar *s, *ends, *us;
417c2fbfb3SApril Chin int found;
427c2fbfb3SApril Chin Sfrsrv_t* rsrv;
437c2fbfb3SApril Chin SFMTXDECL(f);
44da2e3ebdSchin
457c2fbfb3SApril Chin SFMTXENTER(f, NIL(char*));
46da2e3ebdSchin
47da2e3ebdSchin if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) )
48da2e3ebdSchin SFMTXRETURN(f, NIL(char*));
49da2e3ebdSchin SFLOCK(f,0);
50da2e3ebdSchin
51da2e3ebdSchin /* buffer to be returned */
52da2e3ebdSchin rsrv = NIL(Sfrsrv_t*);
53da2e3ebdSchin us = NIL(uchar*);
54da2e3ebdSchin un = 0;
55da2e3ebdSchin found = 0;
56da2e3ebdSchin
57da2e3ebdSchin /* compatibility mode */
58da2e3ebdSchin type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type;
59da2e3ebdSchin
60da2e3ebdSchin if(type&SF_LASTR) /* return the broken record */
617c2fbfb3SApril Chin { if((f->flags&SF_STRING) && (un = f->endb - f->next))
627c2fbfb3SApril Chin { us = f->next;
637c2fbfb3SApril Chin f->next = f->endb;
647c2fbfb3SApril Chin found = 1;
657c2fbfb3SApril Chin }
667c2fbfb3SApril Chin else if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0)
67da2e3ebdSchin { us = rsrv->data;
68da2e3ebdSchin found = 1;
69da2e3ebdSchin }
70da2e3ebdSchin goto done;
71da2e3ebdSchin }
72da2e3ebdSchin
73da2e3ebdSchin while(!found)
74da2e3ebdSchin { /* fill buffer if necessary */
75da2e3ebdSchin if((n = (ends = f->endb) - (s = f->next)) <= 0)
76da2e3ebdSchin { /* for unseekable devices, peek-read 1 record */
77da2e3ebdSchin f->getr = rc;
78da2e3ebdSchin f->mode |= SF_RC;
79da2e3ebdSchin
80da2e3ebdSchin /* fill buffer the conventional way */
81da2e3ebdSchin if(SFRPEEK(f,s,n) <= 0)
82da2e3ebdSchin { us = NIL(uchar*);
83da2e3ebdSchin goto done;
84da2e3ebdSchin }
85da2e3ebdSchin else
86da2e3ebdSchin { ends = s+n;
87da2e3ebdSchin if(f->mode&SF_RC)
88da2e3ebdSchin { s = ends[-1] == rc ? ends-1 : ends;
89da2e3ebdSchin goto do_copy;
90da2e3ebdSchin }
91da2e3ebdSchin }
92da2e3ebdSchin }
93da2e3ebdSchin
94da2e3ebdSchin #if _lib_memchr
95da2e3ebdSchin if(!(s = (uchar*)memchr((char*)s,rc,n)))
96da2e3ebdSchin s = ends;
97da2e3ebdSchin #else
98da2e3ebdSchin while(*s != rc)
99da2e3ebdSchin if((s += 1) == ends)
100da2e3ebdSchin break;
101da2e3ebdSchin #endif
102da2e3ebdSchin do_copy:
103da2e3ebdSchin if(s < ends) /* found separator */
104da2e3ebdSchin { s += 1; /* include the separator */
105da2e3ebdSchin found = 1;
106da2e3ebdSchin
107da2e3ebdSchin if(!us &&
108da2e3ebdSchin (!(type&SF_STRING) || !(f->flags&SF_STRING) ||
109da2e3ebdSchin ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) )
110da2e3ebdSchin { /* returning data in buffer */
111da2e3ebdSchin us = f->next;
112da2e3ebdSchin un = s - f->next;
113da2e3ebdSchin f->next = s;
114da2e3ebdSchin goto done;
115da2e3ebdSchin }
116da2e3ebdSchin }
117da2e3ebdSchin
118da2e3ebdSchin /* amount to be read */
119da2e3ebdSchin n = s - f->next;
120da2e3ebdSchin
1217c2fbfb3SApril Chin if(!found && (_Sfmaxr > 0 && un+n+1 >= _Sfmaxr || (f->flags&SF_STRING))) /* already exceed limit */
122da2e3ebdSchin { us = NIL(uchar*);
123da2e3ebdSchin goto done;
124da2e3ebdSchin }
125da2e3ebdSchin
126da2e3ebdSchin /* get internal buffer */
127da2e3ebdSchin if(!rsrv || rsrv->size < un+n+1)
128da2e3ebdSchin { if(rsrv)
129da2e3ebdSchin rsrv->slen = un;
130da2e3ebdSchin if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*))
131da2e3ebdSchin us = rsrv->data;
132da2e3ebdSchin else
133da2e3ebdSchin { us = NIL(uchar*);
134da2e3ebdSchin goto done;
135da2e3ebdSchin }
136da2e3ebdSchin }
137da2e3ebdSchin
138da2e3ebdSchin /* now copy data */
139da2e3ebdSchin s = us+un;
140da2e3ebdSchin un += n;
141da2e3ebdSchin ends = f->next;
142da2e3ebdSchin f->next += n;
143da2e3ebdSchin MEMCPY(s,ends,n);
144da2e3ebdSchin }
145da2e3ebdSchin
146da2e3ebdSchin done:
147da2e3ebdSchin _Sfi = f->val = un;
148da2e3ebdSchin f->getr = 0;
149da2e3ebdSchin if(found && rc != 0 && (type&SF_STRING) )
150da2e3ebdSchin { us[un-1] = '\0';
151da2e3ebdSchin if(us >= f->data && us < f->endb)
152da2e3ebdSchin { f->getr = rc;
153da2e3ebdSchin f->mode |= SF_GETR;
154da2e3ebdSchin }
155da2e3ebdSchin }
156da2e3ebdSchin
157da2e3ebdSchin /* prepare for a call to get the broken record */
158da2e3ebdSchin if(rsrv)
159da2e3ebdSchin rsrv->slen = found ? 0 : -un;
160da2e3ebdSchin
161da2e3ebdSchin SFOPEN(f,0);
162da2e3ebdSchin
163da2e3ebdSchin if(us && (type&SF_LOCKR) )
164da2e3ebdSchin { f->mode |= SF_PEEK|SF_GETR;
165da2e3ebdSchin f->endr = f->data;
166da2e3ebdSchin }
167da2e3ebdSchin
168da2e3ebdSchin SFMTXRETURN(f, (char*)us);
169da2e3ebdSchin }
170