1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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;
43*b30d1939SAndy Fiddaman 	SFMTXDECL(f); /* declare a local stream variable for multithreading */
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