| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109 |
- /*
- * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Chris Wilson.
- *
- * Contributor(s):
- * Chris Wilson <chris@chris-wilson.co.uk>
- */
- #include "config.h"
- #include "cairo-script-private.h"
- #include <stdio.h>
- #include <limits.h> /* INT_MAX */
- #include <string.h>
- #include <zlib.h>
- #if HAVE_LZO
- #include <lzo/lzo2a.h>
- #endif
- #define CHUNK_SIZE 32768
- #define OWN_STREAM 0x1
- csi_status_t
- csi_file_new (csi_t *ctx,
- csi_object_t *obj,
- const char *path, const char *mode)
- {
- csi_file_t *file;
- file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
- if (file == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- file->base.type = CSI_OBJECT_TYPE_FILE;
- file->base.ref = 1;
- file->data = NULL;
- file->type = STDIO;
- file->flags = OWN_STREAM;
- file->src = fopen (path, mode);
- if (file->src == NULL) {
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
- }
- file->data = _csi_alloc (ctx, CHUNK_SIZE);
- if (file->data == NULL) {
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- }
- file->bp = file->data;
- file->rem = 0;
- obj->type = CSI_OBJECT_TYPE_FILE;
- obj->datum.file = file;
- return CAIRO_STATUS_SUCCESS;
- }
- csi_status_t
- csi_file_new_for_stream (csi_t *ctx,
- csi_object_t *obj,
- FILE *stream)
- {
- csi_file_t *file;
- file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
- if (file == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- file->base.type = CSI_OBJECT_TYPE_FILE;
- file->base.ref = 1;
- file->data = NULL;
- file->type = STDIO;
- file->flags = 0;
- file->src = stream;
- if (file->src == NULL) {
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
- }
- file->data = _csi_alloc (ctx, CHUNK_SIZE);
- if (file->data == NULL) {
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- }
- file->bp = file->data;
- file->rem = 0;
- obj->type = CSI_OBJECT_TYPE_FILE;
- obj->datum.file = file;
- return CAIRO_STATUS_SUCCESS;
- }
- csi_status_t
- csi_file_new_for_bytes (csi_t *ctx,
- csi_object_t *obj,
- const char *bytes,
- unsigned int length)
- {
- csi_file_t *file;
- file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
- if (file == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- file->base.type = CSI_OBJECT_TYPE_FILE;
- file->base.ref = 1;
- file->type = BYTES;
- file->src = (uint8_t *) bytes;
- file->data = (uint8_t *) bytes;
- file->bp = (uint8_t *) bytes;
- file->rem = length;
- obj->type = CSI_OBJECT_TYPE_FILE;
- obj->datum.file = file;
- return CAIRO_STATUS_SUCCESS;
- }
- csi_status_t
- csi_file_new_from_string (csi_t *ctx,
- csi_object_t *obj,
- csi_string_t *src)
- {
- csi_file_t *file;
- file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
- if (_csi_unlikely (file == NULL))
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- file->base.type = CSI_OBJECT_TYPE_FILE;
- file->base.ref = 1;
- if (src->deflate) {
- uLongf len = src->deflate;
- csi_object_t tmp_obj;
- csi_string_t *tmp_str;
- csi_status_t status;
- status = csi_string_new (ctx, &tmp_obj, NULL, src->deflate);
- if (_csi_unlikely (status))
- return status;
- tmp_str = tmp_obj.datum.string;
- switch (src->method) {
- case NONE:
- default:
- status = _csi_error (CAIRO_STATUS_NO_MEMORY);
- break;
- case ZLIB:
- #if HAVE_ZLIB
- if (uncompress ((Bytef *) tmp_str->string, &len,
- (Bytef *) src->string, src->len) != Z_OK)
- #endif
- status = _csi_error (CAIRO_STATUS_NO_MEMORY);
- break;
- case LZO:
- #if HAVE_LZO
- if (lzo2a_decompress ((lzo_bytep) src->string, src->len,
- (lzo_bytep) tmp_str->string, &len,
- NULL))
- #endif
- status = _csi_error (CAIRO_STATUS_NO_MEMORY);
- break;
- }
- if (_csi_unlikely (status)) {
- csi_string_free (ctx, tmp_str);
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- return status;
- }
- file->src = tmp_str;
- file->data = tmp_str->string;
- file->rem = tmp_str->len;
- } else {
- file->src = src; src->base.ref++;
- file->data = src->string;
- file->rem = src->len;
- }
- file->type = BYTES;
- file->bp = file->data;
- obj->type = CSI_OBJECT_TYPE_FILE;
- obj->datum.file = file;
- return CAIRO_STATUS_SUCCESS;
- }
- static csi_status_t
- _csi_file_new_filter (csi_t *ctx,
- csi_object_t *obj,
- csi_object_t *src,
- const csi_filter_funcs_t *funcs,
- void *data)
- {
- csi_file_t *file;
- csi_object_t src_file;
- csi_status_t status;
- file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
- if (file == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- obj->type = CSI_OBJECT_TYPE_FILE;
- obj->datum.file = file;
- file->base.type = CSI_OBJECT_TYPE_FILE;
- file->base.ref = 1;
- file->type = FILTER;
- file->data = data;
- file->filter = funcs;
- status = csi_object_as_file (ctx, src, &src_file);
- if (status) {
- csi_object_free (ctx, obj);
- return status;
- }
- file->src = src_file.datum.file;
- return CAIRO_STATUS_SUCCESS;
- }
- #if 0
- csi_status_t
- csi_file_new_from_stream (csi_t *ctx,
- FILE *file,
- csi_object_t **out)
- {
- csi_file_t *obj;
- obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
- if (obj == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- obj->type = STDIO;
- obj->src = file;
- obj->data = _csi_alloc (ctx, CHUNK_SIZE);
- if (obj->data == NULL) {
- csi_object_free (&obj->base);
- return _csi_error (CAIRO_STATUS_UNDEFINED_FILENAME_ERROR);
- }
- obj->bp = obj->data;
- obj->rem = 0;
- *out = &obj->base;
- return CAIRO_STATUS_SUCCESS;
- }
- static csi_object_t *
- _csi_file_new_from_procedure (csi_t *ctx, csi_object_t *src)
- {
- csi_file_t *obj;
- obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
- if (obj == NULL)
- return NULL;
- obj->type = PROCEDURE;
- obj->src = csi_object_reference (src);
- obj->data = NULL;
- return &obj->base;
- }
- #endif
- typedef struct _ascii85_decode_data {
- uint8_t buf[CHUNK_SIZE];
- uint8_t *bp;
- short bytes_available;
- short eod;
- } _ascii85_decode_data_t;
- static int
- _getc_skip_whitespace (csi_file_t *src)
- {
- int c;
- do switch ((c = csi_file_getc (src))) {
- case 0x0:
- case 0x9:
- case 0xa:
- case 0xc:
- case 0xd:
- case 0x20:
- continue;
- default:
- return c;
- } while (TRUE);
- return c;
- }
- static void
- _ascii85_decode (csi_file_t *file)
- {
- _ascii85_decode_data_t *data = file->data;
- unsigned int n;
- if (data->eod)
- return;
- data->bp = data->buf;
- n = 0;
- do {
- unsigned int v = _getc_skip_whitespace (file->src);
- if (v == 'z') {
- data->buf[n+0] = 0;
- data->buf[n+1] = 0;
- data->buf[n+2] = 0;
- data->buf[n+3] = 0;
- } else if (v == '~') {
- _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
- data->eod = TRUE;
- break;
- } else if (v < '!' || v > 'u') {
- /* IO_ERROR */
- data->eod = TRUE;
- break;
- } else {
- unsigned int i;
- v -= '!';
- for (i = 1; i < 5; i++) {
- int c = _getc_skip_whitespace (file->src);
- if (c == '~') { /* short tuple */
- _getc_skip_whitespace (file->src); /* == '>' || IO_ERROR */
- data->eod = TRUE;
- switch (i) {
- case 0:
- case 1:
- /* IO_ERROR */
- break;
- case 2:
- v = v * (85*85*85) + 85*85*85 -1;
- goto odd1;
- case 3:
- v = v * (85*85) + 85*85 -1;
- goto odd2;
- case 4:
- v = v * 85 + 84;
- data->buf[n+2] = v >> 8 & 0xff;
- odd2:
- data->buf[n+1] = v >> 16 & 0xff;
- odd1:
- data->buf[n+0] = v >> 24 & 0xff;
- data->bytes_available = n + i - 1;
- return;
- }
- break;
- }
- v = 85*v + c-'!';
- }
- data->buf[n+0] = v >> 24 & 0xff;
- data->buf[n+1] = v >> 16 & 0xff;
- data->buf[n+2] = v >> 8 & 0xff;
- data->buf[n+3] = v >> 0 & 0xff;
- }
- n += 4;
- } while (n < sizeof (data->buf) && data->eod == FALSE);
- data->bytes_available = n;
- }
- static int
- _ascii85_decode_getc (csi_file_t *file)
- {
- _ascii85_decode_data_t *data = file->data;
- if (data->bytes_available == 0) {
- _ascii85_decode (file);
- if (data->bytes_available == 0)
- return EOF;
- }
- data->bytes_available--;
- return *data->bp++;
- }
- static void
- _ascii85_decode_putc (csi_file_t *file, int c)
- {
- _ascii85_decode_data_t *data = file->data;
- data->bytes_available++;
- data->bp--;
- }
- static int
- _ascii85_decode_read (csi_file_t *file, uint8_t *buf, int len)
- {
- _ascii85_decode_data_t *data = file->data;
- if (data->bytes_available == 0) {
- _ascii85_decode (file);
- if (data->bytes_available == 0)
- return 0;
- }
- if (len > data->bytes_available)
- len = data->bytes_available;
- memcpy (buf, data->bp, len);
- data->bp += len;
- data->bytes_available -= len;
- return len;
- }
- csi_status_t
- csi_file_new_ascii85_decode (csi_t *ctx,
- csi_object_t *obj,
- csi_dictionary_t *dict,
- csi_object_t *src)
- {
- static const csi_filter_funcs_t funcs = {
- _ascii85_decode_getc,
- _ascii85_decode_putc,
- _ascii85_decode_read,
- _csi_free,
- };
- _ascii85_decode_data_t *data;
- data = _csi_alloc0 (ctx, sizeof (_ascii85_decode_data_t));
- if (data == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- return _csi_file_new_filter (ctx, obj, src, &funcs, data);
- }
- #if HAVE_ZLIB
- #include <zlib.h>
- typedef struct _deflate_decode_data {
- z_stream zlib_stream;
- uint8_t in[CHUNK_SIZE];
- uint8_t out[CHUNK_SIZE];
- int bytes_available;
- uint8_t *bp;
- } _deflate_decode_data_t;
- static void
- _deflate_decode (csi_file_t *file)
- {
- _deflate_decode_data_t *data = file->data;
- uint8_t *bp;
- int len;
- data->zlib_stream.next_out = data->out;
- data->zlib_stream.avail_out = sizeof (data->out);
- bp = data->in;
- len = sizeof (data->in);
- if (data->zlib_stream.avail_in) {
- memmove (data->in,
- data->zlib_stream.next_in,
- data->zlib_stream.avail_in);
- len -= data->zlib_stream.avail_in;
- bp += data->zlib_stream.avail_in;
- }
- len = csi_file_read (file->src, bp, len);
- data->zlib_stream.next_in = data->in;
- data->zlib_stream.avail_in += len;
- inflate (&data->zlib_stream, len == 0 ? Z_FINISH : Z_NO_FLUSH);
- data->bytes_available = data->zlib_stream.next_out - data->out;
- data->bp = data->out;
- }
- static int
- _deflate_decode_getc (csi_file_t *file)
- {
- _deflate_decode_data_t *data = file->data;
- if (data->bytes_available == 0) {
- _deflate_decode (file);
- if (data->bytes_available == 0)
- return EOF;
- }
- data->bytes_available--;
- return *data->bp++;
- }
- static void
- _deflate_decode_putc (csi_file_t *file, int c)
- {
- _deflate_decode_data_t *data = file->data;
- data->bytes_available++;
- data->bp--;
- }
- static int
- _deflate_decode_read (csi_file_t *file, uint8_t *buf, int len)
- {
- _deflate_decode_data_t *data = file->data;
- if (data->bytes_available == 0) {
- _deflate_decode (file);
- if (data->bytes_available == 0)
- return 0;
- }
- if (len > (int) data->bytes_available)
- len = data->bytes_available;
- memcpy (buf, data->bp, len);
- data->bp += len;
- data->bytes_available -= len;
- return len;
- }
- static void
- _deflate_destroy (csi_t *ctx, void *closure)
- {
- _deflate_decode_data_t *data;
- data = closure;
- inflateEnd (&data->zlib_stream);
- _csi_free (ctx, data);
- }
- csi_status_t
- csi_file_new_deflate_decode (csi_t *ctx,
- csi_object_t *obj,
- csi_dictionary_t *dict,
- csi_object_t *src)
- {
- static const csi_filter_funcs_t funcs = {
- _deflate_decode_getc,
- _deflate_decode_putc,
- _deflate_decode_read,
- _deflate_destroy,
- };
- _deflate_decode_data_t *data;
- data = _csi_alloc (ctx, sizeof (_deflate_decode_data_t));
- if (data == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- data->zlib_stream.zalloc = Z_NULL;
- data->zlib_stream.zfree = Z_NULL;
- data->zlib_stream.opaque = Z_NULL;
- data->zlib_stream.next_in = data->in;
- data->zlib_stream.avail_in = 0;
- data->zlib_stream.next_out = data->out;
- data->zlib_stream.avail_out = sizeof (data->out);
- data->bytes_available = 0;
- if (inflateInit (&data->zlib_stream) != Z_OK) {
- _csi_free (ctx, data);
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- }
- return _csi_file_new_filter (ctx, obj, src, &funcs, data);
- }
- #endif
- #if 0
- static int
- hex_value (int c)
- {
- if (c < '0')
- return EOF;
- if (c <= '9')
- return c - '0';
- c |= 32;
- if (c < 'a')
- return EOF;
- if (c <= 'f')
- return c - 'a' + 0xa;
- return EOF;
- }
- /* Adobe Type 1 Font Format book: p63 */
- typedef struct _decrypt_data {
- uint8_t putback[32];
- uint8_t nputback;
- csi_bool_t is_hexadecimal;
- unsigned short R;
- int eod;
- } _decrypt_data_t;
- static uint8_t
- _decrypt (unsigned short *R, uint8_t cypher)
- {
- #define c1 52845
- #define c2 22719
- uint8_t plain;
- plain = cypher ^ (*R >> 8);
- *R = (cypher + *R) * c1 + c2;
- return plain;
- #undef c1
- #undef c2
- }
- int
- csi_decrypt (uint8_t *in, int length,
- unsigned short salt, int binary,
- uint8_t *out)
- {
- const uint8_t * const end = in + length;
- uint8_t *base = out;
- while (in < end) {
- int c;
- if (! binary) {
- int c_hi = -1, c_lo = 0;
- while (in < end && (c_hi = *in++)) {
- switch (c_hi) {
- case 0x0:
- case 0x9:
- case 0xa:
- case 0xc:
- case 0xd:
- case 0x20:
- continue;
- default:
- break;
- }
- }
- if (c_hi < 0)
- break;
- while (in < end && (c_lo = *in++)) {
- switch (c_lo) {
- case 0x0:
- case 0x9:
- case 0xa:
- case 0xc:
- case 0xd:
- case 0x20:
- continue;
- default:
- break;
- }
- }
- c = (hex_value (c_hi) << 4) | hex_value (c_lo);
- } else
- c = *in++;
- *out++ = _decrypt (&salt, c);
- }
- return out - base;
- }
- static uint8_t
- _encrypt (unsigned short *R, uint8_t plain)
- {
- #define c1 52845
- #define c2 22719
- uint8_t cypher;
- cypher = plain ^ (*R >> 8);
- *R = (cypher + *R) * c1 + c2;
- return cypher;
- #undef c1
- #undef c2
- }
- int
- csi_encrypt (uint8_t *in, int length,
- unsigned short salt, int discard, int binary,
- uint8_t *out)
- {
- const char hex[]="0123456789abcdef";
- const uint8_t * const end = in + length;
- uint8_t *base = out;
- int col = 0;
- while (discard--) {
- if (! binary) {
- int c = _encrypt (&salt, ' ');
- *out++ = hex[(c >> 4) & 0xf];
- *out++ = hex[(c >> 0) & 0xf];
- } else
- *out++ = _encrypt (&salt, 0);
- }
- while (in < end) {
- int c;
- c = _encrypt (&salt, *in++);
- if (! binary) {
- if (col == 78) {
- *out++ = '\n';
- col = 0;
- }
- *out++ = hex[(c >> 4) & 0xf];
- *out++ = hex[(c >> 0) & 0xf];
- col += 2;
- } else
- *out++ = c;
- }
- return out - base;
- }
- static int
- _decrypt_getc (csi_file_t *file)
- {
- _decrypt_data_t *data = file->data;
- int c;
- if (data->nputback)
- return data->putback[--data->nputback];
- if (data->is_hexadecimal) {
- int c_hi, c_lo;
- c_hi = _getc_skip_whitespace (file->src);
- c_lo = _getc_skip_whitespace (file->src);
- c = (hex_value (c_hi) << 4) | hex_value (c_lo);
- } else
- c = csi_file_getc (file->src);
- if (c == EOF)
- return EOF;
- return _decrypt (&data->R, c);
- }
- static void
- _decrypt_putc (csi_file_t *file, int c)
- {
- _decrypt_data_t *data;
- data = file->data;
- data->putback[data->nputback++] = c;
- }
- csi_object_t *
- csi_file_new_decrypt (csi_t *ctx, csi_object_t *src, int salt, int discard)
- {
- csi_object_t *obj;
- _decrypt_data_t *data;
- int n;
- data = _csi_alloc0 (ctx, sizeof (_decrypt_data_t));
- if (data == NULL)
- return NULL;
- data->R = salt;
- obj = _csi_file_new_filter (ctx, src,
- _decrypt_getc,
- _decrypt_putc,
- NULL,
- _csi_free,
- data);
- if (obj == NULL)
- return NULL;
- /* XXX determine encoding, eexec only? */
- data->is_hexadecimal = salt != 4330;
- for (n = 0; n < discard; n++) {
- int c;
- c = csi_file_getc (obj);
- if (c == EOF) {
- return obj;
- }
- }
- return obj;
- }
- #endif
- csi_status_t
- _csi_file_execute (csi_t *ctx, csi_file_t *obj)
- {
- return _csi_scan_file (ctx, obj);
- }
- int
- csi_file_getc (csi_file_t *file)
- {
- int c;
- if (_csi_unlikely (file->src == NULL))
- return EOF;
- switch (file->type) {
- case STDIO:
- if (_csi_likely (file->rem)) {
- c = *file->bp++;
- file->rem--;
- } else {
- file->rem = fread (file->bp = file->data, 1, CHUNK_SIZE, file->src);
- case BYTES:
- if (_csi_likely (file->rem)) {
- c = *file->bp++;
- file->rem--;
- } else
- c = EOF;
- }
- break;
- case PROCEDURE:
- #if 0
- if (file->data == NULL) {
- csi_status_t status;
- csi_object_t *string;
- RERUN_PROCEDURE:
- status = csi_object_execute (file->src);
- if (status)
- return EOF;
- string = csi_pop_operand (file->base.ctx);
- if (string == NULL)
- return EOF;
- file->data = csi_object_as_file (file->base.ctx, string);
- csi_object_free (string);
- if (file->data == NULL)
- return EOF;
- }
- c = csi_file_getc (file->data);
- if (c == EOF) {
- csi_object_free (file->data);
- file->data = NULL;
- goto RERUN_PROCEDURE;
- }
- #else
- c = EOF;
- #endif
- break;
- case FILTER:
- c = file->filter->filter_getc (file);
- break;
- default:
- c = EOF;
- break;
- }
- return c;
- }
- int
- csi_file_read (csi_file_t *file, void *buf, int len)
- {
- int ret;
- if (file->src == NULL)
- return 0;
- switch (file->type) {
- case STDIO:
- if (file->rem > 0) {
- ret = len;
- if (file->rem < ret)
- ret = file->rem;
- memcpy (buf, file->bp, ret);
- file->bp += ret;
- file->rem -= ret;
- } else
- ret = fread (buf, 1, len, file->src);
- break;
- case BYTES:
- if (file->rem > 0) {
- ret = len;
- if (file->rem < ret)
- ret = file->rem;
- memcpy (buf, file->bp, ret);
- file->bp += ret;
- file->rem -= ret;
- } else
- ret = 0;
- break;
- case PROCEDURE:
- #if 0
- if (file->data == NULL) {
- csi_status_t status;
- csi_object_t *string;
- RERUN_PROCEDURE:
- status = csi_object_execute (file->src);
- if (status)
- return 0;
- string = csi_pop_operand (file->base.ctx);
- if (string == NULL)
- return 0;
- file->data = csi_object_as_file (file->base.ctx, string);
- csi_object_free (string);
- if (file->data == NULL)
- return 0;
- }
- ret = csi_file_read (file->data, buf, len);
- if (ret == 0) {
- csi_object_free (file->data);
- file->data = NULL;
- goto RERUN_PROCEDURE;
- }
- #else
- ret = 0;
- #endif
- break;
- case FILTER:
- ret = file->filter->filter_read (file, buf, len);
- break;
- default:
- ret = 0;
- break;
- }
- return ret;
- }
- void
- csi_file_putc (csi_file_t *file, int c)
- {
- if (file->src == NULL)
- return;
- switch ((int) file->type) {
- case STDIO:
- case BYTES:
- file->bp--;
- file->rem++;
- break;
- case FILTER:
- file->filter->filter_putc (file, c);
- break;
- default:
- break;
- }
- }
- void
- csi_file_flush (csi_file_t *file)
- {
- if (file->src == NULL)
- return;
- switch ((int) file->type) {
- case FILTER: /* need to eat EOD */
- while (csi_file_getc (file) != EOF)
- ;
- break;
- default:
- break;
- }
- }
- void
- csi_file_close (csi_t *ctx, csi_file_t *file)
- {
- if (file->src == NULL)
- return;
- switch (file->type) {
- case STDIO:
- if (file->flags & OWN_STREAM)
- fclose (file->src);
- break;
- case BYTES:
- if (file->src != file->data) {
- csi_string_t *src = file->src;
- if (src != NULL && --src->base.ref == 0)
- csi_string_free (ctx, src);
- }
- break;
- case FILTER:
- {
- csi_file_t *src = file->src;
- if (src != NULL && --src->base.ref == 0)
- _csi_file_free (ctx, src);
- }
- break;
- case PROCEDURE:
- default:
- break;
- }
- file->src = NULL;
- }
- void
- _csi_file_free (csi_t *ctx, csi_file_t *file)
- {
- csi_file_flush (file);
- /* XXX putback */
- csi_file_close (ctx, file);
- switch (file->type) {
- case BYTES:
- break;
- case PROCEDURE:
- #if 0
- csi_object_free (ctx, file->data);
- #endif
- break;
- case STDIO:
- _csi_free (ctx, file->data);
- break;
- case FILTER:
- file->filter->filter_destroy (ctx, file->data);
- break;
- default:
- break;
- }
- _csi_slab_free (ctx, file, sizeof (csi_file_t));
- }
- csi_status_t
- _csi_file_as_string (csi_t *ctx,
- csi_file_t *file,
- csi_object_t *obj)
- {
- char *bytes;
- unsigned int len;
- unsigned int allocated;
- csi_status_t status;
- allocated = 16384;
- bytes = _csi_alloc (ctx, allocated);
- if (bytes == NULL)
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- len = 0;
- do {
- int ret;
- ret = csi_file_read (file, bytes + len, allocated - len);
- if (ret == 0)
- break;
- len += ret;
- if (len + 1 > allocated / 2) {
- char *newbytes;
- int newlen;
- if (_csi_unlikely (allocated > INT_MAX / 2))
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- newlen = allocated * 2;
- newbytes = _csi_realloc (ctx, bytes, newlen);
- if (_csi_unlikely (newbytes == NULL)) {
- _csi_free (ctx, bytes);
- return _csi_error (CAIRO_STATUS_NO_MEMORY);
- }
- bytes = newbytes;
- allocated = newlen;
- }
- } while (TRUE);
- bytes[len] = '\0'; /* better safe than sorry! */
- status = csi_string_new_from_bytes (ctx, obj, bytes, len);
- if (status) {
- _csi_free (ctx, bytes);
- return status;
- }
- return CAIRO_STATUS_SUCCESS;
- }
|