summaryrefslogtreecommitdiff
path: root/source/fitz/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/fitz/output.c')
-rw-r--r--source/fitz/output.c183
1 files changed, 113 insertions, 70 deletions
diff --git a/source/fitz/output.c b/source/fitz/output.c
index 027f66c3..e39dd352 100644
--- a/source/fitz/output.c
+++ b/source/fitz/output.c
@@ -3,61 +3,74 @@
struct fz_output_s
{
void *opaque;
- int (*printf)(fz_context *, void *opaque, const char *, va_list ap);
int (*write)(fz_context *, void *opaque, const void *, int n);
+ void (*seek)(fz_context *, void *opaque, fz_off_t off, int whence);
+ fz_off_t (*tell)(fz_context *, void *opaque);
void (*close)(fz_context *, void *opaque);
};
static int
-file_printf(fz_context *ctx, void *opaque, const char *fmt, va_list ap)
+file_write(fz_context *ctx, void *opaque, const void *buffer, int count)
{
FILE *file = opaque;
- return fz_vfprintf(ctx, file, fmt, ap);
+ size_t n = fwrite(buffer, 1, count, file);
+ if (n < count && ferror(file))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot fwrite: %s", strerror(errno));
+ return n;
}
-static int
-file_write(fz_context *ctx, void *opaque, const void *buffer, int count)
+static void
+file_seek(fz_context *ctx, void *opaque, fz_off_t off, int whence)
{
FILE *file = opaque;
- return fwrite(buffer, 1, count, file);
+ int n = fz_fseek(file, off, whence);
+ if (n < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot fseek: %s", strerror(errno));
+}
+
+static fz_off_t
+file_tell(fz_context *ctx, void *opaque)
+{
+ FILE *file = opaque;
+ fz_off_t off = fz_ftell(file);
+ if (off == -1)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot ftell: %s", strerror(errno));
+ return off;
}
static void
file_close(fz_context *ctx, void *opaque)
{
FILE *file = opaque;
- fclose(file);
+ int n = fclose(file);
+ if (n < 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot fclose: %s", strerror(errno));
}
fz_output *
-fz_new_output_with_file(fz_context *ctx, FILE *file, int close)
+fz_new_output_with_file_ptr(fz_context *ctx, FILE *file, int close)
{
fz_output *out = fz_malloc_struct(ctx, fz_output);
out->opaque = file;
- out->printf = file_printf;
out->write = file_write;
+ out->seek = file_seek;
+ out->tell = file_tell;
out->close = close ? file_close : NULL;
return out;
}
fz_output *
-fz_new_output_to_filename(fz_context *ctx, const char *filename)
+fz_new_output_with_path(fz_context *ctx, const char *filename, int append)
{
fz_output *out = NULL;
- FILE *file = fz_fopen(filename, "wb");
+ FILE *file = fz_fopen(filename, append ? "ab" : "wb");
if (!file)
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- fz_var(ctx);
-
fz_try(ctx)
{
- out = fz_malloc_struct(ctx, fz_output);
- out->opaque = file;
- out->printf = file_printf;
- out->write = file_write;
- out->close = file_close;
+ out = fz_new_output_with_file_ptr(ctx, file, 1);
}
fz_catch(ctx)
{
@@ -67,84 +80,114 @@ fz_new_output_to_filename(fz_context *ctx, const char *filename)
return out;
}
-void
-fz_drop_output(fz_context *ctx, fz_output *out)
+static int
+buffer_write(fz_context *ctx, void *opaque, const void *data, int len)
{
- if (!out)
- return;
- if (out->close)
- out->close(ctx, out->opaque);
- fz_free(ctx, out);
+ fz_buffer *buffer = opaque;
+ fz_write_buffer(ctx, buffer, (unsigned char *)data, len);
+ return len;
}
-int
-fz_printf(fz_context *ctx, fz_output *out, const char *fmt, ...)
+static void
+buffer_seek(fz_context *ctx, void *opaque, fz_off_t off, int whence)
{
- int ret;
- va_list ap;
-
- if (!out)
- return 0;
+ fz_throw(ctx, FZ_ERROR_GENERIC, "cannot seek in buffer: %s", strerror(errno));
+}
- va_start(ap, fmt);
- ret = out->printf(ctx, out->opaque, fmt, ap);
- va_end(ap);
+static fz_off_t
+buffer_tell(fz_context *ctx, void *opaque)
+{
+ fz_buffer *buffer = opaque;
+ return buffer->len;
+}
- return ret;
+static void
+buffer_close(fz_context *ctx, void *opaque)
+{
+ fz_buffer *buffer = opaque;
+ fz_drop_buffer(ctx, buffer);
}
-int
-fz_write(fz_context *ctx, fz_output *out, const void *data, int len)
+fz_output *
+fz_new_output_with_buffer(fz_context *ctx, fz_buffer *buf)
{
- if (!out)
- return 0;
- return out->write(ctx, out->opaque, data, len);
+ fz_output *out = fz_malloc_struct(ctx, fz_output);
+ out->opaque = fz_keep_buffer(ctx, buf);
+ out->write = buffer_write;
+ out->seek = buffer_seek;
+ out->tell = buffer_tell;
+ out->close = buffer_close;
+ return out;
}
void
-fz_putc(fz_context *ctx, fz_output *out, char c)
+fz_drop_output(fz_context *ctx, fz_output *out)
{
- if (out)
- (void)out->write(ctx, out->opaque, &c, 1);
+ if (!out) return;
+ if (out->close)
+ out->close(ctx, out->opaque);
+ fz_free(ctx, out);
}
-int
-fz_puts(fz_context *ctx, fz_output *out, const char *str)
+void
+fz_seek_output(fz_context *ctx, fz_output *out, fz_off_t off, int whence)
{
- if (!out)
- return 0;
- return out->write(ctx, out->opaque, str, strlen(str));
+ if (!out) return;
+ out->seek(ctx, out->opaque, off, whence);
}
-static int
-buffer_printf(fz_context *ctx, void *opaque, const char *fmt, va_list list)
+fz_off_t
+fz_tell_output(fz_context *ctx, fz_output *out)
{
- fz_buffer *buffer = opaque;
- return fz_buffer_vprintf(ctx, buffer, fmt, list);
+ if (!out) return 0;
+ return out->tell(ctx, out->opaque);
}
-static int
-buffer_write(fz_context *ctx, void *opaque, const void *data, int len)
+void
+fz_vprintf(fz_context *ctx, fz_output *out, const char *fmt, va_list old_args)
{
- fz_buffer *buffer = opaque;
- fz_write_buffer(ctx, buffer, (unsigned char *)data, len);
- return len;
+ char buffer[256], *p = buffer;
+ int len;
+ va_list args;
+
+ if (!out) return;
+
+ /* First try using our fixed size buffer */
+ va_copy(args, old_args);
+ len = fz_vsnprintf(buffer, sizeof buffer, fmt, args);
+ va_copy_end(args);
+
+ /* If that failed, allocate a big enough buffer */
+ if (len >= sizeof buffer)
+ {
+ p = fz_malloc(ctx, len + 1);
+ va_copy(args, old_args);
+ fz_vsnprintf(p, len + 1, fmt, args);
+ va_copy_end(args);
+ }
+
+ fz_try(ctx)
+ out->write(ctx, out->opaque, p, len);
+ fz_always(ctx)
+ if (p != buffer)
+ fz_free(ctx, p);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
}
-static void
-buffer_close(fz_context *ctx, void *opaque)
+void
+fz_printf(fz_context *ctx, fz_output *out, const char *fmt, ...)
{
- fz_buffer *buffer = opaque;
- fz_drop_buffer(ctx, buffer);
+ va_list args;
+ if (!out) return;
+ va_start(args, fmt);
+ fz_vprintf(ctx, out, fmt, args);
+ va_end(args);
}
-fz_output *
-fz_new_output_with_buffer(fz_context *ctx, fz_buffer *buf)
+int
+fz_write(fz_context *ctx, fz_output *out, const void *data, int len)
{
- fz_output *out = fz_malloc_struct(ctx, fz_output);
- out->opaque = fz_keep_buffer(ctx, buf);
- out->printf = buffer_printf;
- out->write = buffer_write;
- out->close = buffer_close;
- return out;
+ if (!out) return 0;
+ return out->write(ctx, out->opaque, data, len);
}