/*------------------------------------------------------------ * Vport Getb */ static int vport_getb(ScmPort *p) { vport *data = (vport*)p->src.vt.data; SCM_ASSERT(data != NULL); if (SCM_FALSEP(data->getb_proc)) { /* If the port doesn't have get-byte method, use get-char if possible. */ ScmObj ch; ScmChar c; char buf[SCM_CHAR_MAX_BYTES]; int nb, i; if (SCM_FALSEP(data->getc_proc)) return EOF; ch = Scm_ApplyRec(data->getc_proc, SCM_NIL); if (!SCM_CHARP(ch)) return EOF; c = SCM_CHAR_VALUE(ch); nb = SCM_CHAR_NBYTES(c); SCM_CHAR_PUT(buf, c); for (i=1; i<nb; i++) { /* pushback for later use. this isn't very efficient; if efficiency becomes a problem, we need another API to pushback multiple bytes. */ Scm_UngetbUnsafe(buf[i], p); } return buf[0]; } else { ScmObj b = Scm_ApplyRec(data->getb_proc, SCM_NIL); if (!SCM_INTP(b)) return EOF; return (SCM_INT_VALUE(b) & 0xff); } }
void Scm_UngetbUnsafe(int b, ScmPort *p) #endif { VMDECL; SHORTCUT(p, Scm_UngetbUnsafe(b, p); return); LOCK(p); if (p->ungotten != SCM_CHAR_INVALID || p->scrcnt >= SCM_CHAR_MAX_BYTES) { Scm_PortError(p, SCM_PORT_ERROR_INPUT, "pushback buffer overflow on port %S", p); } p->scratch[p->scrcnt++] = b; UNLOCK(p); }
/* NB: this routine reads bytes, not chars. It allows to readline from a port in unknown character encoding (e.g. reading the first line of xml doc to find out charset parameter). */ ScmObj readline_body(ScmPort *p) { ScmDString ds; Scm_DStringInit(&ds); int b1 = Scm_GetbUnsafe(p); if (b1 == EOF) return SCM_EOF; for (;;) { if (b1 == EOF) return Scm_DStringGet(&ds, 0); if (b1 == '\n') break; if (b1 == '\r') { int b2 = Scm_GetbUnsafe(p); if (b2 == EOF || b2 == '\n') break; Scm_UngetbUnsafe(b2, p); break; } SCM_DSTRING_PUTB(&ds, b1); b1 = Scm_GetbUnsafe(p); } p->line++; return Scm_DStringGet(&ds, 0); }