aboutsummaryrefslogtreecommitdiff
path: root/gfsm/gfsm/src/libgfsm/gfsmIO.c
diff options
context:
space:
mode:
Diffstat (limited to 'gfsm/gfsm/src/libgfsm/gfsmIO.c')
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmIO.c558
1 files changed, 558 insertions, 0 deletions
diff --git a/gfsm/gfsm/src/libgfsm/gfsmIO.c b/gfsm/gfsm/src/libgfsm/gfsmIO.c
new file mode 100644
index 0000000..f5e637d
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmIO.c
@@ -0,0 +1,558 @@
+/*=============================================================================*\
+ * File: gfsmIO.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: I/O
+ *
+ * Copyright (c) 2006-2008 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER
+ * OF ALL WARRANTIES, see the file "COPYING" in this distribution.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmConfig.h>
+
+#include <glib.h>
+#include <gfsmIO.h>
+//#include <gfsmCompat.h>
+#include <gfsmUtils.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#if 0
+#include <fcntl.h>
+#endif
+#include <errno.h>
+
+#ifdef GFSM_ZLIB_ENABLED
+# include <zlib.h>
+# define GFSM_DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION
+#endif
+
+#include "vasprintf.h"
+#include "getdelim.h"
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: C FILE*
+ */
+void gfsmio_close_cfile(FILE *f);
+void gfsmio_flush_cfile(FILE *f);
+gboolean gfsmio_eof_cfile(FILE *f);
+gboolean gfsmio_read_cfile(FILE *f, void *buf, size_t nbytes);
+ssize_t gfsmio_getdelim_cfile(FILE *f, char **lineptr, size_t *n, int delim);
+gboolean gfsmio_write_cfile(FILE *f, const void *buf, size_t nbytes);
+#ifdef HAVE_VFPRINTF
+int gfsmio_vprintf_cfile(FILE *f, const char *fmt, va_list *app);
+#endif
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: gzFile
+ */
+#ifdef GFSM_ZLIB_ENABLED
+void gfsmio_close_zfile(gzFile zf);
+void gfsmio_flush_zfile(gzFile zf);
+gboolean gfsmio_eof_zfile(gzFile zf);
+gboolean gfsmio_read_zfile(gzFile zf, void *buf, size_t nbytes);
+gboolean gfsmio_write_zfile(gzFile zf, const void *buf, size_t nbytes);
+#endif
+
+/*======================================================================
+ * Protos: I/O: Handles: Methods: Instatiations: GString*
+ */
+void gfsmio_close_gstring(gfsmPosGString *pgs);
+gboolean gfsmio_eof_gstring(gfsmPosGString *pgs);
+gboolean gfsmio_read_gstring(gfsmPosGString *pgs, void *buf, size_t nbytes);
+gboolean gfsmio_write_gstring(gfsmPosGString *pgs, const void *buf, size_t nbytes);
+
+/*======================================================================
+ * I/O: Handles: Constructors etc.
+ */
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_handle_new(gfsmIOHandleType typ, void *handle_data)
+{
+ gfsmIOHandle *ioh = g_new0(gfsmIOHandle,1);
+ ioh->iotype = typ;
+ ioh->handle = handle_data;
+
+ switch (typ) {
+ //--------------------------------
+ case gfsmIOTCFile:
+#ifndef GFSM_ZLIB_ENABLED
+ case gfsmIOTZFile:
+#endif
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_cfile;
+ ioh->getdelim_func= (gfsmIOGetdelimFunc)gfsmio_getdelim_cfile;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_cfile;
+#ifdef HAVE_VFPRINTF
+ ioh->vprintf_func = (gfsmIOVprintfFunc)gfsmio_vprintf_cfile;
+#endif
+
+ ioh->flush_func = (gfsmIOFlushFunc)gfsmio_flush_cfile;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_cfile;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_cfile;
+ break;
+
+#ifdef GFSM_ZLIB_ENABLED
+ //--------------------------------
+ case gfsmIOTZFile:
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_zfile;
+ //ioh->getdelim_func= (gfsmIOReadFunc)gfsmio_getdelim_zfile;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_zfile;
+ //ioh->vprintf_func = (gfsmIOReadFunc)gfsmio_vprintf_zfile;
+
+ ioh->flush_func = (gfsmIOFlushFunc)gfsmio_flush_zfile;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_zfile;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_zfile;
+ break;
+#endif
+
+ //--------------------------------
+ case gfsmIOTGString:
+ ioh->read_func = (gfsmIOReadFunc)gfsmio_read_gstring;
+ //ioh->getdelim_func= gfsmio_getdelim_gstring;
+
+ ioh->write_func = (gfsmIOWriteFunc)gfsmio_write_gstring;
+ //ioh->vprintf_func = gfsmio_vprintf_gstring;
+
+ //ioh->flush_func = gfsmio_flush_gstring;
+ ioh->close_func = (gfsmIOCloseFunc)gfsmio_close_gstring;
+ ioh->eof_func = (gfsmIOEofFunc)gfsmio_eof_gstring;
+ break;
+
+ //--------------------------------
+ case gfsmIOTUser:
+ default:
+ break;
+ }
+
+ return ioh;
+}
+
+/*--------------------------------------------------------------*/
+void gfsmio_handle_free(gfsmIOHandle *ioh)
+{
+ g_free(ioh);
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_file(FILE *f)
+{
+ return gfsmio_handle_new(gfsmIOTCFile, f);
+}
+
+/*--------------------------------------------------------------*/
+#undef GFSM_ZFILE_USE_FCNTL
+gfsmIOHandle *gfsmio_new_zfile(FILE *f, const char *mode, int compress_level)
+{
+#ifdef GFSM_ZLIB_ENABLED
+# ifdef GFSM_ZFILE_USE_FCNTL
+ int fd = fileno(f);
+ int flags = fcntl(fd, F_GETFL);
+ gzFile zf;
+# if 0 /* DEBUG */
+ //-- DEBUG
+ const int o_rdwr = O_RDWR;
+ const int o_rdonly = O_RDONLY;
+ const int o_wronly = O_WRONLY;
+ //-- /DEBUG
+# endif /* DEBUG */
+ if ( (flags&O_RDWR) == O_RDWR ) {
+ zf = gzdopen(dup(fd),"rwb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ else
+ if ( (flags&O_WRONLY) == O_WRONLY ) {
+ zf = gzdopen(fd,"wb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ else { // if ( (flags&O_RDONLY) == O_RDONLY )
+ zf = gzdopen(fd,"rb");
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+ return gfsmio_handle_new(gfsmIOTZFile, zf);
+
+# else /* !defined(GFSM_ZFILE_USE_FCNTL) */
+
+ if (compress_level != 0) {
+ //-- use compression
+ gzFile zf = gzdopen(fileno(f), mode);
+ if (strchr(mode,'w')) gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ return gfsmio_handle_new(gfsmIOTZFile, zf);
+ } else {
+ return gfsmio_new_file( fdopen(dup(fileno(f)), mode) );
+ }
+
+# endif /* GFSM_ZFILE_USE_FCNTL */
+
+#else /* !defined(GFSM_ZLIB_ENABLED) */
+
+ return gfsmio_new_file( fdopen(dup(fileno(f)), mode) );
+#endif
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_filename(const char *filename, const char *mode, int compress_level, gfsmError **errp)
+{
+#ifdef GFSM_ZLIB_ENABLED
+ if (compress_level != 0) {
+ gzFile zf;
+ if (strcmp(filename,"-")==0) {
+ if (strchr(mode,'w')) zf = gzdopen(dup(fileno(stdout)), mode);
+ else zf = gzdopen(dup(fileno(stdin)), mode);
+ }
+ else if (!(zf = gzopen(filename,mode))) {
+ int errnum;
+ const char *zerror = gzerror(zf,&errnum);
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("gzopen"), //-- code
+ "gzopen() failed for file '%s': %s",
+ filename,
+ errnum==Z_ERRNO ? strerror(errno) : zerror);
+ return NULL;
+ }
+
+ //-- set compression level
+ if (compress_level < 0) compress_level = GFSM_DEFAULT_COMPRESSION;
+ if (strchr(mode,'w')) {
+ gzsetparams(zf, compress_level, Z_DEFAULT_STRATEGY);
+ }
+
+ return gfsmio_handle_new(gfsmIOTZFile,zf);
+ }
+ else {
+#endif
+ FILE *f;
+ if (strcmp(filename,"-")==0) {
+ if (strchr(mode,'w')) f = stdout;
+ else f = stdin;
+ }
+ else if (!(f = fopen(filename,mode))) {
+ g_set_error(errp,
+ g_quark_from_static_string("gfsm"), //-- domain
+ g_quark_from_static_string("fopen"), //-- code
+ "open failed for file '%s': %s",
+ filename, strerror(errno));
+ }
+ return gfsmio_new_file(f);
+#ifdef GFSM_ZLIB_ENABLED
+ }
+#endif
+}
+
+/*--------------------------------------------------------------*/
+gfsmIOHandle *gfsmio_new_gstring(gfsmPosGString *pgs)
+{
+ return gfsmio_handle_new(gfsmIOTGString, pgs);
+}
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Basic
+ */
+
+/*--------------------------------------------------------------*/
+/** flush all data to an output handle (calls \a flush_func) */
+void gfsmio_close(gfsmIOHandle *ioh)
+{
+ if (ioh->close_func) (*ioh->close_func)(ioh->handle);
+}
+
+/*--------------------------------------------------------------*/
+/** flush all data to an output handle (calls \a flush_func) */
+void gfsmio_flush(gfsmIOHandle *ioh)
+{
+ if (ioh->flush_func) (*ioh->flush_func)(ioh->handle);
+}
+
+/*--------------------------------------------------------------*/
+/** returns true if \a h is at EOF, false otherwise or if no \a eof_func is defined */
+gboolean gfsmio_eof(gfsmIOHandle *ioh)
+{
+ if (ioh->eof_func) return (*ioh->eof_func)(ioh->handle);
+ return FALSE;
+}
+
+
+
+/*======================================================================
+ * I/O: Handles: Methods: Read
+ */
+
+/*--------------------------------------------------------------*/
+int gfsmio_getc(gfsmIOHandle *ioh)
+{
+ if (gfsmio_eof(ioh)) return GFSMIO_EOF;
+ else {
+ //-- getc() --> read()
+ unsigned char c = 0;
+ if (gfsmio_read(ioh, &c, 1)) return (int)c;
+ }
+ return GFSMIO_EOF;
+}
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_read(gfsmIOHandle *ioh, void *buf, size_t nbytes)
+{
+ if (ioh->read_func) return (*ioh->read_func)(ioh->handle, buf, nbytes);
+
+ g_printerr("gfsmio_read(): no method defined for handle of type %d\n", ioh->iotype);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------*/
+ssize_t gfsmio_getline(gfsmIOHandle *ioh, char **lineptr, size_t *n)
+{
+ return gfsmio_getdelim(ioh, lineptr, n, '\n');
+}
+
+/*--------------------------------------------------------------*/
+ssize_t gfsmio_getdelim(gfsmIOHandle *ioh, char **lineptr, size_t *n, int delim)
+{
+ if (ioh->getdelim_func) {
+ return (*ioh->getdelim_func)(ioh->handle, lineptr, n, delim);
+ }
+ else {
+ //-- getdelim() --> getc()
+ ssize_t i = 0;
+ int c = -2;
+ GString *gs=NULL;
+
+ while ( *n > 0 && i < (*n-1) && (c=gfsmio_getc(ioh)) != GFSMIO_EOF ) {
+ (*lineptr)[i++] = c;
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got char %d ~ '%c' to linebuf\n", i, (char)c, c);//--DEBUG
+#endif
+ if ((char)c == (char)delim) {
+ (*lineptr)[i] = '\0';
+ return i;
+ }
+ }
+ if (c == GFSMIO_EOF) {
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got EOF reading to linebuf\n", i);//--DEBUG
+#endif
+ (*lineptr)[i] = '\0';
+ return i == 0 ? GFSMIO_EOF : i;
+ }
+
+ //-- oops: buffer overflow
+ gs = g_string_new_len((i>0 ? *lineptr : ""), i);
+ while ( (c=gfsmio_getc(ioh)) != GFSMIO_EOF ) {
+ g_string_append_c(gs,c);
+ i++;
+#ifdef GFSM_DEBUG_GETDELIM
+ fprintf(stderr, "---> getdelim(i=%d) got char %d ~ '%c' to GString*\n", i, (char)c, c);//--DEBUG
+#endif
+ if ((char)c == (char)delim) break;
+ }
+
+#ifdef GFSM_DEBUG_GETDELIM
+ if (c==GFSMIO_EOF) { fprintf(stderr, "---> getdelim(i=%d) got EOF reading to GString*\n", i); }//--DEBUG
+#endif
+
+ //-- maybe free old line buffer
+ if (*lineptr) free(*lineptr);
+
+ //-- set up new buffer
+ g_string_append_c(gs,0); //-- this shouldn't be necessary, but weird things happen otherwise (bug?)
+
+ //-- the following code breaks in Perl on OpenSuSE 11.0 [maybe GString doesn't use malloc ?!], --moocow 2008-10-31
+ /*
+ *lineptr = gs->str; //-- copy literal GString data buffer
+ *n = gs->allocated_len; //-- ... and its length
+ g_string_free(gs,FALSE); //-- ... and only free GString wrapper struct; not the data buffer
+ */
+ //-- ...so we do this instead (ugly but functional):
+ *lineptr = (char *)malloc(gs->allocated_len); //-- malloc a copy of GString data buffer
+ memcpy(*lineptr, gs->str, gs->allocated_len); //-- ... and copy the data
+ *n = gs->allocated_len; //-- ... and its length
+ g_string_free(gs,TRUE); //-- ... and free the whole GString and its data buffer
+
+ return i==0 && c==GFSMIO_EOF ? GFSMIO_EOF : i;
+ }
+ return GFSMIO_EOF;
+}
+
+/*======================================================================
+ * I/O: Handles: Methods: Write
+ */
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_putc(gfsmIOHandle *ioh, int c)
+{
+ return gfsmio_write(ioh, &c, 1);
+}
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_puts(gfsmIOHandle *ioh, const char *s)
+{
+ return gfsmio_write(ioh, s, strlen(s));
+}
+
+
+/*--------------------------------------------------------------*/
+gboolean gfsmio_write(gfsmIOHandle *ioh, const void *buf, size_t nbytes)
+{
+ if (ioh->write_func) return (*ioh->write_func)(ioh->handle, buf, nbytes);
+
+ g_printerr("gfsmio_read(): no method defined for handle of type %d\n", ioh->iotype);
+ return FALSE;
+}
+
+/*--------------------------------------------------------------*/
+int gfsmio_printf(gfsmIOHandle *io, const char *fmt, ...)
+{
+ int len;
+ va_list ap;
+
+ va_start(ap,fmt);
+ len = gfsmio_vprintf(io, fmt, &ap);
+ va_end(ap);
+
+ return len;
+}
+
+/*--------------------------------------------------------------*/
+int gfsmio_vprintf(gfsmIOHandle *io, const char *fmt, va_list *app)
+{
+ char *obuf = NULL;
+ size_t len = 0;
+ gboolean rc;
+ len = vasprintf(&obuf, fmt, *app);
+ rc = gfsmio_write(io, obuf, len);
+ if (obuf) free(obuf);
+ return rc ? len : 0;
+}
+
+
+/*======================================================================
+ * I/O: Handles: Methods: FILE*
+ */
+
+/*--------------------------------------------------------------
+ * FILE*: Basic Methods
+ */
+void gfsmio_flush_cfile(FILE *f)
+{ if (f) fflush(f); }
+
+void gfsmio_close_cfile(FILE *f)
+{
+ if (f && f != stdin && f != stdout && f != stderr) fclose(f);
+}
+
+gboolean gfsmio_eof_cfile(FILE *f)
+{ return f ? feof(f) : FALSE; }
+
+/*--------------------------------------------------------------
+ * FILE*: Read Methods
+ */
+gboolean gfsmio_read_cfile(FILE *f, void *buf, size_t nbytes)
+{ return f ? (fread(buf,nbytes,1,f)==1) : FALSE; }
+
+ssize_t gfsmio_getdelim_cfile(FILE *f, char **lineptr, size_t *n, int delim)
+{ return f ? getdelim(lineptr, n, delim, f) : 0; }
+
+/*--------------------------------------------------------------
+ * FILE*: Write Methods
+ */
+gboolean gfsmio_write_cfile(FILE *f, const void *buf, size_t nbytes)
+{ return f ? (fwrite(buf, nbytes, 1, f)==1) : FALSE; }
+
+#ifdef HAVE_VFPRINTF
+int gfsmio_vprintf_cfile(FILE *f, const char *fmt, va_list *app)
+{ return f ? vfprintf(f, fmt, *app) : 0; }
+#endif
+
+/*======================================================================
+ * I/O: Handles: Methods: gzFile
+ */
+#ifdef GFSM_ZLIB_ENABLED
+
+/*--------------------------------------------------------------
+ * gzFile: Basic Methods
+ */
+void gfsmio_close_zfile(gzFile zf)
+{ if (zf) gzclose(zf); }
+
+void gfsmio_flush_zfile(gzFile zf)
+{ if (zf) gzflush(zf,Z_SYNC_FLUSH); }
+
+gboolean gfsmio_eof_zfile(gzFile zf)
+{ return zf ? gzeof(zf) : FALSE; }
+
+/*--------------------------------------------------------------
+ * gzFile: Read Methods
+ */
+gboolean gfsmio_read_zfile(gzFile zf, void *buf, size_t nbytes)
+{ return zf ? (gzread(zf,buf,nbytes)==nbytes) : FALSE; }
+
+/*--------------------------------------------------------------
+ * gzFile: Write Methods
+ */
+gboolean gfsmio_write_zfile(gzFile zf, const void *buf, size_t nbytes)
+{ return zf ? (gzwrite(zf, buf, nbytes)==nbytes) : FALSE; }
+
+#endif /* GFSM_ZLIB_ENABLED */
+
+
+/*======================================================================
+ * I/O: Handles: Methods: GString*
+ */
+
+/*--------------------------------------------------------------
+ * GString*: Basic Methods
+ */
+
+void gfsmio_close_gstring(gfsmPosGString *pgs)
+{ if (pgs) pgs->pos = 0; }
+
+gboolean gfsmio_eof_gstring(gfsmPosGString *pgs)
+{ return pgs && pgs->gs ? (pgs->pos >= pgs->gs->len) : TRUE; }
+
+/*--------------------------------------------------------------
+ * GString*: Read Methods
+ */
+gboolean gfsmio_read_gstring(gfsmPosGString *pgs, void *buf, size_t nbytes)
+{
+ if (!pgs || !pgs->gs || pgs->pos > pgs->gs->len) return FALSE;
+ if (pgs->pos+nbytes <= pgs->gs->len) {
+ //-- normal case: read it in
+ memcpy(buf, pgs->gs->str + pgs->pos, nbytes);
+ pgs->pos += nbytes;
+ return TRUE;
+ }
+ //-- overflow: grab what we can
+ memcpy(buf, pgs->gs->str + pgs->pos, pgs->gs->len-pgs->pos);
+ pgs->pos = pgs->gs->len;
+ return FALSE;
+}
+
+/*--------------------------------------------------------------
+ * GString*: Write Methods
+ */
+gboolean gfsmio_write_gstring(gfsmPosGString *pgs, const void *buf, size_t nbytes)
+{
+ if (pgs && pgs->gs) {
+ g_string_append_len(pgs->gs, buf, nbytes);
+ return TRUE;
+ }
+ return FALSE;
+}