#include "sfhdr.h"
#if __STD_C
char* sfgetr(reg Sfio_t *f, reg int rc, int type)
#else
char* sfgetr(f,rc,type)
reg Sfio_t* f;
reg int rc;
int type;
#endif
{
reg ssize_t n;
reg uchar *s, *ends, *us;
reg ssize_t un;
reg int found;
reg Sfrsrv_t* rsrv;
SFMTXSTART(f, NIL(char*));
if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) )
SFMTXRETURN(f, NIL(char*));
SFLOCK(f,0);
rsrv = NIL(Sfrsrv_t*);
us = NIL(uchar*);
un = 0;
found = 0;
type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type;
if(type&SF_LASTR)
{ if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0)
{ us = rsrv->data;
found = 1;
}
goto done;
}
while(!found)
{
if((n = (ends = f->endb) - (s = f->next)) <= 0)
{
f->getr = rc;
f->mode |= SF_RC;
if(SFRPEEK(f,s,n) <= 0)
{ us = NIL(uchar*);
goto done;
}
else
{ ends = s+n;
if(f->mode&SF_RC)
{ s = ends[-1] == rc ? ends-1 : ends;
goto do_copy;
}
}
}
#if _lib_memchr
if(!(s = (uchar*)memchr((char*)s,rc,n)))
s = ends;
#else
while(*s != rc)
if((s += 1) == ends)
break;
#endif
do_copy:
if(s < ends)
{ s += 1;
found = 1;
if(!us &&
(!(type&SF_STRING) || !(f->flags&SF_STRING) ||
((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) )
{
us = f->next;
un = s - f->next;
f->next = s;
goto done;
}
}
n = s - f->next;
if(!rsrv || rsrv->size < un+n+1)
{ if(rsrv)
rsrv->slen = un;
if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*))
us = rsrv->data;
else
{ us = NIL(uchar*);
goto done;
}
}
s = us+un;
un += n;
ends = f->next;
f->next += n;
MEMCPY(s,ends,n);
}
done:
_Sfi = f->val = un;
f->getr = 0;
if(found && rc != 0 && (type&SF_STRING) )
{ us[un-1] = '\0';
if(us >= f->data && us < f->endb)
{ f->getr = rc;
f->mode |= SF_GETR;
}
}
if(rsrv)
rsrv->slen = found ? 0 : -un;
SFOPEN(f,0);
if(us && (type&SF_LOCKR) )
{ f->mode |= SF_PEEK|SF_GETR;
f->endr = f->data;
}
SFMTXRETURN(f, (char*)us);
}