/* libwmf (stream.c): library for wmf conversion Copyright (C) 2001 The Free Software Foundation The libwmf Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The libwmf Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the libwmf Library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "wmfconfig.h" #endif #include #include "wmfdefs.h" #include "stream.h" /** * Open a compressed character output stream. * * @param API the API handle * @param out descriptor for a zlib compressed file stream * * wmf_ztream_create() creates a \b wmfStream (a character-based output stream) for output to a file opened * via \b zlib. (Writing compressed data to memory is not currently supported.) * * @return Returns a \b wmfStream pointer, or zero on failure. * Possible library error state of \b wmf_E_InsMem. */ wmfStream* wmf_ztream_create (wmfAPI* API,gzFile out) { wmfStream* stream = 0; wmfDefaultZtream* defstr = 0; if (out == 0) { WMF_DEBUG (API,"memory ztream (compressed stream) not supported"); return (0); } defstr = wmf_malloc (API,sizeof (wmfDefaultZtream)); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); return (0); } defstr->API = API; defstr->out = out; defstr->offset = 0; /* Can't reset them anyway. */ defstr->max = 0; defstr->len = 0; defstr->buf = 0; defstr->ptr = 0; stream = wmf_malloc (API,sizeof (wmfStream)); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); if (defstr->buf) wmf_free (API,defstr->buf); wmf_free (API,defstr); return (0); } stream->context = (void*) defstr; stream->sputs = wmf_stream_zputs; stream->reset = wmf_stream_rezet; return (stream); } /** * Open an uncompressed character output stream. * * @param API the API handle * @param out descriptor for a file stream; or zero to write to memory * * wmf_stream_create() creates a \b wmfStream (a character-based output stream) for output to a file or, if * \p out is zero, to memory. * * @return Returns a \b wmfStream pointer, or zero on failure. * Possible library error states of \b wmf_E_InsMem or \b wmf_E_BadFile. */ wmfStream* wmf_stream_create (wmfAPI* API,FILE* out) { wmfStream* stream = 0; wmfDefaultStream* defstr = 0; defstr = wmf_malloc (API,sizeof (wmfDefaultStream)); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); return (0); } defstr->API = API; if (out) { defstr->out = out; defstr->offset = ftell (out); if ((defstr->offset < 0) && ((API->flags & WMF_OPT_IGNORE_NONFATAL) == 0)) { WMF_ERROR (API,"wmf_stream_create: ftell failed on output stream"); API->err = wmf_E_BadFile; wmf_free (API,defstr); return (0); } defstr->max = 0; defstr->len = 0; defstr->buf = 0; defstr->ptr = 0; } else { defstr->out = 0; defstr->offset = 0; defstr->max = 256; defstr->len = 0; defstr->buf = wmf_malloc (API,defstr->max * sizeof (char)); defstr->ptr = defstr->buf; if (ERR (API)) { WMF_DEBUG (API,"bailing..."); wmf_free (API,defstr); return (0); } } stream = wmf_malloc (API,sizeof (wmfStream)); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); if (defstr->buf) wmf_free (API,defstr->buf); wmf_free (API,defstr); return (0); } stream->context = (void*) defstr; stream->sputs = wmf_stream_sputs; stream->reset = wmf_stream_reset; return (stream); } /** * Close a compressed character output stream. * * @param API the API handle * @param stream stream handle * @param buffer (unused) * @param length (unused) */ void wmf_ztream_destroy (wmfAPI* API,wmfStream* stream,char** buffer,unsigned long* length) { wmfDefaultZtream* defstr = 0; if (stream == 0) return; defstr = (wmfDefaultZtream*) stream->context; (*(defstr->ptr)) = 0; if (buffer) (*buffer) = defstr->buf; if (length) (*length) = defstr->len; wmf_free (API,stream->context); wmf_free (API,(void*) stream); } /** * Close an uncompressed character output stream. * * @param API the API handle * @param stream stream handle * @param buffer for memory return * @param length for length return * * In the case of write-to-memory, on return \p *buffer is an array of length \p length. */ void wmf_stream_destroy (wmfAPI* API,wmfStream* stream,char** buffer,unsigned long* length) { wmfDefaultStream* defstr = 0; if (stream == 0) return; defstr = (wmfDefaultStream*) stream->context; (*(defstr->ptr)) = 0; if (buffer) (*buffer) = defstr->buf; if (length) (*length) = defstr->len; wmf_free (API,stream->context); wmf_free (API,(void*) stream); } /** * Formatted print to character output stream. * * @param API the API handle * @param stream stream handle * @param format print format * * With syntax similar to printf(), wmf_stream_printf() prints a formatted message to a \b wmfStream * character stream. * * @return Returns the number of characters written, or zero on failure. * Possible library error state of \b wmf_E_InsMem. */ int wmf_stream_printf (wmfAPI* API,wmfStream* stream,char* format,...) { int length; va_list argp; va_start (argp,format); for (;;) { length = vsnprintf (API->string_buffer.buffer,API->string_buffer.length,format,argp); if ((length >= 0) && (length < (API->string_buffer.length - 1))) break; /* i.e., success */ if (wmf_strbuf_grow (API) == 0) break; /* i.e., probably a memory failure */ } va_end (argp); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); return (0); } stream->sputs (API->string_buffer.buffer,stream->context); return (length); } /** * @internal */ int wmf_stream_zputs (char* str,void* context) { wmfDefaultZtream* defstr = (wmfDefaultZtream*) context; return (gzputs (defstr->out,str)); } /** * @internal */ int wmf_stream_sputs (char* str,void* context) { char* more = 0; char* sptr = 0; unsigned long max=0; wmfDefaultStream* defstr = (wmfDefaultStream*) context; wmfAPI* API = defstr->API; if (defstr->out) { return (fputs (str,defstr->out)); } sptr = str; while (*sptr) { if ((defstr->len + 1) == defstr->max) { more = (char*) wmf_realloc (API,defstr->buf,(defstr->max + 256) * sizeof (char)); if (ERR (API)) { WMF_DEBUG (API,"bailing..."); defstr->max = max; return (EOF); } defstr->max += 256; defstr->buf = more; defstr->ptr = defstr->buf + defstr->len; } (*(defstr->ptr)) = (*sptr); defstr->ptr++; defstr->len++; sptr++; } return (0); } /** * @internal */ int wmf_stream_rezet (void* context) { WMF_DEBUG (((wmfDefaultZtream*) context)->API, "cannot reset ztream (compressed stream)"); return (0); } /** * @internal */ int wmf_stream_reset (void* context) { wmfDefaultStream* defstr = (wmfDefaultStream*) context; if (defstr->out) { return (fseek (defstr->out,defstr->offset,SEEK_SET)); } else { defstr->len = 0; defstr->ptr = defstr->buf; return (0); } }