/*------------------------------------------------------------ * 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); } }
/* handle the case that there's an ungotten char */ static int getb_ungotten(ScmPort *p) { SCM_CHAR_PUT(p->scratch, p->ungotten); p->scrcnt = SCM_CHAR_NBYTES(p->ungotten); p->ungotten = SCM_CHAR_INVALID; return getb_scratch(p); }
static int chartoucs(ScmChar ch) { #if defined(GAUCHE_CHAR_ENCODING_UTF_8) if (ch == SCM_CHAR_INVALID) return -1; return (int)ch; #else /*!GAUCHE_CHAR_ENCODING_UTF_8*/ char inbuf[6], outbuf[6]; const char *inb = inbuf; char *outb = outbuf; if (ch == SCM_CHAR_INVALID) return -1; if (ucsconv.char2ucs == NULL) return -1; size_t inroom = SCM_CHAR_NBYTES(ch); size_t outroom = 6; SCM_CHAR_PUT(inbuf, ch); (void)SCM_INTERNAL_MUTEX_LOCK(ucsconv.mutex); size_t r = jconv(ucsconv.char2ucs, &inb, &inroom, &outb, &outroom); (void)SCM_INTERNAL_MUTEX_UNLOCK(ucsconv.mutex); if (r == INPUT_NOT_ENOUGH || r == OUTPUT_NOT_ENOUGH) { Scm_Error("can't convert character %u to UCS4 code: implementation problem?", ch); } if (r == ILLEGAL_SEQUENCE) { return -1; } else { unsigned char *ucp = (unsigned char*)outbuf; if (ucp[0] < 0x80) return (int)ucp[0]; if (ucp[0] < 0xe0) { return ((ucp[0]&0x1f)<<6) + (ucp[1]&0x3f); } if (ucp[0] < 0xf0) { return ((ucp[0]&0x0f)<<12) + ((ucp[1]&0x3f)<<6) + (ucp[2]&0x3f); } if (ucp[0] < 0xf8) { return ((ucp[0]&0x07)<<18) + ((ucp[1]&0x3f)<<12) + ((ucp[2]&0x3f)<<6) + (ucp[3]&0x3f); } if (ucp[0] < 0xfc) { return ((ucp[0]&0x03)<<24) + ((ucp[1]&0x3f)<<18) + ((ucp[2]&0x3f)<<12) + ((ucp[3]&0x3f)<<6) + (ucp[4]&0x3f); } if (ucp[0] < 0xfe) { return ((ucp[0]&0x01)<<30) + ((ucp[1]&0x3f)<<24) + ((ucp[2]&0x3f)<<18) + ((ucp[3]&0x3f)<<12) + ((ucp[4]&0x3f)<<6) + (ucp[5]&0x3f); } return -1; } #endif /*!GAUCHE_CHAR_ENCODING_UTF_8*/ }
int Scm_GetzUnsafe(char *buf, int buflen, ScmPort *p) #endif { VMDECL; SHORTCUT(p, return Scm_GetzUnsafe(buf, buflen, p)); LOCK(p); CLOSE_CHECK(p); if (p->scrcnt) { int r = GETZ_SCRATCH(buf, buflen, p); UNLOCK(p); return r; } if (p->ungotten != SCM_CHAR_INVALID) { p->scrcnt = SCM_CHAR_NBYTES(p->ungotten); SCM_CHAR_PUT(p->scratch, p->ungotten); p->ungotten = SCM_CHAR_INVALID; int r = GETZ_SCRATCH(buf, buflen, p); UNLOCK(p); return r; } switch (SCM_PORT_TYPE(p)) { case SCM_PORT_FILE: { int siz = 0; SAFE_CALL(p, siz = bufport_read(p, buf, buflen)); p->bytes += siz; UNLOCK(p); if (siz == 0) return EOF; else return siz; } case SCM_PORT_ISTR: { int r = GETZ_ISTR(p, buf, buflen); p->bytes += r; UNLOCK(p); return r; } case SCM_PORT_PROC: { int r = 0; SAFE_CALL(p, r = p->src.vt.Getz(buf, buflen, p)); p->bytes += r; UNLOCK(p); return r; } default: UNLOCK(p); Scm_PortError(p, SCM_PORT_ERROR_INPUT, "bad port type for input: %S", p); } return -1; /* dummy */ }
void Scm_PutcUnsafe(ScmChar c, ScmPort *p) #endif { VMDECL; SHORTCUT(p, Scm_PutcUnsafe(c, p); return); WALKER_CHECK(p); LOCK(p); CLOSE_CHECK(p); switch (SCM_PORT_TYPE(p)) { case SCM_PORT_FILE: { int nb = SCM_CHAR_NBYTES(c); if (p->src.buf.current+nb > p->src.buf.end) { SAFE_CALL(p, bufport_flush(p, (int)(p->src.buf.current - p->src.buf.buffer), FALSE)); } SCM_ASSERT(p->src.buf.current+nb <= p->src.buf.end); SCM_CHAR_PUT(p->src.buf.current, c); p->src.buf.current += nb; if (SCM_PORT_BUFFER_MODE(p) == SCM_PORT_BUFFER_LINE) { if (c == '\n') { SAFE_CALL(p, bufport_flush(p, nb, FALSE)); } } else if (SCM_PORT_BUFFER_MODE(p) == SCM_PORT_BUFFER_NONE) { SAFE_CALL(p, bufport_flush(p, nb, FALSE)); } UNLOCK(p); break; } case SCM_PORT_OSTR: SCM_DSTRING_PUTC(&p->src.ostr, c); UNLOCK(p); break; case SCM_PORT_PROC: SAFE_CALL(p, p->src.vt.Putc(c, p)); UNLOCK(p); break; default: UNLOCK(p); Scm_PortError(p, SCM_PORT_ERROR_OUTPUT, "bad port type for output: %S", p); } }
/*------------------------------------------------------------ * Vport putc */ static void vport_putc(ScmChar c, ScmPort *p) { vport *data = (vport*)p->src.vt.data; SCM_ASSERT(data != NULL); if (SCM_FALSEP(data->putc_proc)) { if (SCM_FALSEP(data->putb_proc)) { Scm_PortError(p, SCM_PORT_ERROR_OTHER, "cannot perform output to the port %S", p); } else { unsigned char buf[SCM_CHAR_MAX_BYTES]; int i, n=SCM_CHAR_NBYTES(c); SCM_CHAR_PUT(buf, c); for (i=0; i<n; i++) { Scm_ApplyRec(data->putb_proc, SCM_LIST1(SCM_MAKE_INT(buf[i]))); } } } else { Scm_ApplyRec(data->putc_proc, SCM_LIST1(SCM_MAKE_CHAR(c))); } }