+static void consume_buffer(saxctxt* ctx, const char* inbuf,
+ int bytes, int flag) {
+ apr_status_t rv;
+ apr_size_t insz;
+ char* buf;
+#ifndef GO_FASTER
+ int verbose = ctx->cfg->verbose;
+#endif
+ if (ctx->conv_in == NULL) {
+ /* just feed it to libxml2 */
+ htmlParseChunk(ctx->parser, inbuf, bytes, flag) ;
+ return;
+ }
+ if (ctx->conv_in->bytes > 0) {
+ /* FIXME: make this a reusable buf? */
+ buf = apr_palloc(ctx->f->r->pool, ctx->conv_in->bytes + bytes);
+ memcpy(buf, ctx->conv_in->buf, ctx->conv_in->bytes);
+ memcpy(buf + ctx->conv_in->bytes, inbuf, bytes);
+ bytes += ctx->conv_in->bytes;
+ ctx->conv_in->bytes = 0;
+ } else {
+ buf = (char*) inbuf;
+ }
+ insz = bytes;
+ while (insz > 0) {
+ char outbuf[4096];
+ apr_size_t outsz = 4096;
+ rv = apr_xlate_conv_buffer(ctx->conv_in->convset,
+ buf + (bytes - insz), &insz,
+ outbuf, &outsz);
+ htmlParseChunk(ctx->parser, outbuf, 4096-outsz, flag) ;
+ switch (rv) {
+ case APR_SUCCESS:
+ continue;
+ case APR_EINCOMPLETE:
+ if (insz < 32) {/* save dangling byte(s) and return */
+ ctx->conv_in->bytes = insz;
+ ctx->conv_in->buf = (buf != inbuf) ? buf + (bytes-insz)
+ : apr_pmemdup(ctx->f->r->pool, buf + (bytes-insz), insz);
+ return;
+ } else { /*OK, maybe 4096 wasn't big enough, and ended mid-char */
+ continue;
+ }
+ case APR_EINVAL: /* try skipping one bad byte */
+ VERBOSE( ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->f->r,
+ "Skipping invalid byte in input stream!") ) ;
+ --insz;
+ continue;
+ default:
+ /* Erk! What's this? Bail out and eat the buf raw
+ * if libxml2 will accept it!
+ */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, ctx->f->r,
+ "Failed to convert input; trying it raw") ;
+ htmlParseChunk(ctx->parser, buf + (bytes - insz), insz, flag) ;
+ ctx->conv_in = NULL; /* don't try converting any more */
+ return;
+ }
+ }
+}
+static void AP_fwrite(saxctxt* ctx, const char* inbuf, int bytes, int flush) {
+ /* convert charset if necessary, and output */
+ char* buf;
+ apr_status_t rv;
+ apr_size_t insz ;
+#ifndef GO_FASTER
+ int verbose = ctx->cfg->verbose;
+#endif
+
+ if (ctx->conv_out == NULL) {
+ ap_fwrite(ctx->f->next, ctx->bb, inbuf, bytes);
+ return;
+ }
+ if (ctx->conv_out->bytes > 0) {
+ /* FIXME: make this a reusable buf? */
+ buf = apr_palloc(ctx->f->r->pool, ctx->conv_out->bytes + bytes);
+ memcpy(buf, ctx->conv_out->buf, ctx->conv_out->bytes);
+ memcpy(buf + ctx->conv_out->bytes, inbuf, bytes);
+ bytes += ctx->conv_out->bytes;
+ ctx->conv_out->bytes = 0;
+ } else {
+ buf = (char*) inbuf;
+ }
+ insz = bytes;
+ while (insz > 0) {
+ char outbuf[2048];
+ apr_size_t outsz = 2048;
+ rv = apr_xlate_conv_buffer(ctx->conv_out->convset,
+ buf + (bytes - insz), &insz,
+ outbuf, &outsz);
+ ap_fwrite(ctx->f->next, ctx->bb, outbuf, 2048-outsz) ;
+ switch (rv) {
+ case APR_SUCCESS:
+ continue;
+ case APR_EINCOMPLETE: /* save dangling byte(s) and return */
+ /* but if we need to flush, just abandon them */
+ if ( flush) { /* if we're flushing, this must be complete */
+ /* so this is an error */
+ VERBOSE( ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->f->r,
+ "Skipping invalid byte in output stream!") ) ;
+ } else {
+ ctx->conv_out->bytes = insz;
+ ctx->conv_out->buf = (buf != inbuf) ? buf + (bytes-insz)
+ : apr_pmemdup(ctx->f->r->pool, buf + (bytes-insz), insz);
+ }
+ break;
+ case APR_EINVAL: /* try skipping one bad byte */
+ VERBOSE( ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->f->r,
+ "Skipping invalid byte in output stream!") ) ;
+ --insz;
+ continue;
+ default:
+ /* Erk! What's this? Bail out and pass the buf raw
+ * if libxml2 will accept it!
+ */
+ VERBOSE( ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, ctx->f->r,
+ "Failed to convert output; sending UTF-8") ) ;
+ ap_fwrite(ctx->f->next, ctx->bb, buf + (bytes - insz), insz) ;
+ break;
+ }
+ }
+}