SV *readcb;
SV *seekcb;
SV *closecb;
-
- /* we need to remember whether the buffer contains write data or
- read data
- */
- int reading;
- int writing;
-
- /* how far we've read into the buffer (not used for writing) */
- int where;
-
- /* the amount of space used/data available in the buffer */
- int used;
-
- /* the maximum amount to fill the buffer before flushing
- If any write is larger than this then the buffer is flushed and
- the full write is performed. The write is _not_ split into
- maxwrite sized calls
- */
- int maxlength;
-
- char buffer[CBDATA_BUFSIZE];
};
-/*
-
-call_writer(cbd, buf, size)
-
-Low-level function to call the perl writer callback.
-
-*/
-
-static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
- dTHX;
- int count;
- int success;
- SV *sv;
- dSP;
-
- if (!SvOK(cbd->writecb))
- return -1;
-
- ENTER;
- SAVETMPS;
- EXTEND(SP, 1);
- PUSHMARK(SP);
- PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
- PUTBACK;
-
- count = perl_call_sv(cbd->writecb, G_SCALAR);
-
- SPAGAIN;
- if (count != 1)
- croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
- sv = POPs;
- success = SvTRUE(sv);
-
-
- PUTBACK;
- FREETMPS;
- LEAVE;
-
- return success ? size : -1;
-}
-
-static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
- size_t maxread) {
+static ssize_t
+call_reader(struct cbdata *cbd, void *buf, size_t size,
+ size_t maxread) {
dTHX;
int count;
int result;
return result;
}
-static ssize_t write_flush(struct cbdata *cbd) {
- dTHX;
- ssize_t result;
-
- if (cbd->used) {
- result = call_writer(cbd, cbd->buffer, cbd->used);
- cbd->used = 0;
- return result;
- }
- else {
- return 1; /* success of some sort */
- }
-}
-
-static off_t io_seeker(void *p, off_t offset, int whence) {
+static off_t
+io_seeker(void *p, off_t offset, int whence) {
dTHX;
struct cbdata *cbd = p;
int count;
if (!SvOK(cbd->seekcb))
return -1;
- if (cbd->writing) {
- if (cbd->used && write_flush(cbd) <= 0)
- return -1;
- cbd->writing = 0;
- }
- if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
- offset -= cbd->where - cbd->used;
- }
- cbd->reading = 0;
- cbd->where = cbd->used = 0;
-
ENTER;
SAVETMPS;
EXTEND(SP, 2);
return result;
}
-static ssize_t io_writer(void *p, void const *data, size_t size) {
+static ssize_t
+io_writer(void *p, void const *data, size_t size) {
dTHX;
struct cbdata *cbd = p;
+ I32 count;
+ SV *sv;
+ dSP;
+ bool success;
- /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
- if (!cbd->writing) {
- if (cbd->reading && cbd->where < cbd->used) {
- /* we read past the place where the caller expected us to be
- so adjust our position a bit */
- if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
- return -1;
- }
- cbd->reading = 0;
- }
- cbd->where = cbd->used = 0;
- }
- cbd->writing = 1;
- if (cbd->used && cbd->used + size > cbd->maxlength) {
- int write_res = write_flush(cbd);
- if (write_res <= 0) {
- return write_res;
- }
- cbd->used = 0;
- }
- if (cbd->used+size <= cbd->maxlength) {
- memcpy(cbd->buffer + cbd->used, data, size);
- cbd->used += size;
- return size;
- }
- /* it doesn't fit - just pass it up */
- return call_writer(cbd, data, size);
+ if (!SvOK(cbd->writecb))
+ return -1;
+
+ ENTER;
+ SAVETMPS;
+ EXTEND(SP, 1);
+ PUSHMARK(SP);
+ PUSHs(sv_2mortal(newSVpv((char *)data, size)));
+ PUTBACK;
+
+ count = perl_call_sv(cbd->writecb, G_SCALAR);
+
+ SPAGAIN;
+ if (count != 1)
+ croak("Result of perl_call_sv(..., G_SCALAR) != 1");
+
+ sv = POPs;
+ success = SvTRUE(sv);
+
+
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+
+ return success ? size : -1;
}
static ssize_t
io_reader(void *p, void *data, size_t size) {
dTHX;
struct cbdata *cbd = p;
- ssize_t total;
+ ssize_t total = 0;
char *out = data; /* so we can do pointer arithmetic */
- /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
- if (cbd->writing) {
- if (write_flush(cbd) <= 0)
- return 0;
- cbd->writing = 0;
- }
-
- cbd->reading = 1;
- if (size <= cbd->used - cbd->where) {
- /* simplest case */
- memcpy(data, cbd->buffer+cbd->where, size);
- cbd->where += size;
- return size;
- }
- total = 0;
- memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
- total += cbd->used - cbd->where;
- size -= cbd->used - cbd->where;
- out += cbd->used - cbd->where;
- if (size < sizeof(cbd->buffer)) {
- int did_read = 0;
- int copy_size;
- while (size
- && (did_read = call_reader(cbd, cbd->buffer, size,
- sizeof(cbd->buffer))) > 0) {
- cbd->where = 0;
- cbd->used = did_read;
-
- copy_size = i_min(size, cbd->used);
- memcpy(out, cbd->buffer, copy_size);
- cbd->where += copy_size;
- out += copy_size;
- total += copy_size;
- size -= copy_size;
- }
- if (did_read < 0)
- return -1;
- }
- else {
- /* just read the rest - too big for our buffer*/
- int did_read;
- while (size > 0 && (did_read = call_reader(cbd, out, size, size)) > 0) {
- size -= did_read;
- total += did_read;
- out += did_read;
- }
- if (did_read < 0)
- return -1;
+ int did_read;
+ while (size > 0 && (did_read = call_reader(cbd, out, size, size)) > 0) {
+ size -= did_read;
+ total += did_read;
+ out += did_read;
}
+ if (total == 0 && did_read < 0)
+ return -1;
return total;
}
static int io_closer(void *p) {
dTHX;
struct cbdata *cbd = p;
-
- if (cbd->writing && cbd->used > 0) {
- if (write_flush(cbd) < 0)
- return -1;
- cbd->writing = 0;
- }
+ int success = 1;
if (SvOK(cbd->closecb)) {
dSP;
+ I32 count;
+ SV *sv;
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
- perl_call_sv(cbd->closecb, G_VOID);
+ count = perl_call_sv(cbd->closecb, G_SCALAR);
SPAGAIN;
+
+ sv = POPs;
+ success = SvTRUE(sv);
+
PUTBACK;
FREETMPS;
LEAVE;
}
- return 0;
+ return success ? 0 : -1;
}
static void io_destroyer(void *p) {
cbd->seekcb = seekcb;
SvREFCNT_inc(closecb);
cbd->closecb = closecb;
- cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
- if (maxwrite > CBDATA_BUFSIZE)
- maxwrite = CBDATA_BUFSIZE;
- cbd->maxlength = maxwrite;
RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
io_destroyer);
OUTPUT:
size_t bc = 0;
char *cbuf = buf;
- IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %d\n",
- buf, count) );
+ IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
+ buf, (unsigned)count) );
/* Is this a good idea? Would it be better to handle differently?
skip handling? */
while( count!=bc && (rc = ig->readcb(p,cbuf+bc,count-bc))>0 ) {
}
ier->cpos += bc;
- IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d, bc = %d\n", rc, bc) );
+ IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
return rc < 0 ? rc : bc;
}
char *cbuf = (char*)buf;
IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, ier->cpos = %ld, buf = %p, "
- "count = %d\n", ig, (long) ier->cpos, buf, count) );
+ "count = %u\n", ig, (long) ier->cpos, buf, (unsigned)count) );
/* Is this a good idea? Would it be better to handle differently?
skip handling? */
}
ier->cpos += bc;
- IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %d\n", rc, bc) );
+ IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
return rc < 0 ? rc : bc;
}
io_buffer *ig = (io_buffer *)igo;
io_ex_buffer *ieb = igo->exdata;
- IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ieb->cpos = %ld, buf = %p, count = %d\n", (long) ieb->cpos, buf, count) );
+ IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ieb->cpos = %ld, buf = %p, count = %u\n", (long) ieb->cpos, buf, (unsigned)count) );
if ( ieb->cpos+count > ig->len ) {
mm_log((1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ieb->cpos, (long)ig->len, (long)count));
int
i_io_close(io_glue *ig) {
- int flush_res = 0;
int result = 0;
IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
if (flags & I_IO_DUMP_CALLBACKS) {
fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
- fprintf(IOL_DEBs, " writecb: %d\n", ig->writecb);
- fprintf(IOL_DEBs, " seekcb: %d\n", ig->seekcb);
- fprintf(IOL_DEBs, " closecb: %d\n", ig->closecb);
- fprintf(IOL_DEBs, " sizecb: %d\n", ig->sizecb);
+ fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
+ fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
+ fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
+ fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
}
if (flags & I_IO_DUMP_BUFFER) {
fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);