/farmR/src/glplib08.c
https://code.google.com/p/javawfm/ · C · 593 lines · 353 code · 53 blank · 187 comment · 75 complexity · e5b317e07a43e99218fe8b33ccbf0d95 MD5 · raw file
- /* glplib08.c (stream input/output) */
- /***********************************************************************
- * This code is part of GLPK (GNU Linear Programming Kit).
- *
- * Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,
- * Department for Applied Informatics, Moscow Aviation Institute,
- * Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
- *
- * GLPK is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GLPK 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 General Public
- * License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
- ***********************************************************************/
- #define _GLPSTD_ERRNO
- #define _GLPSTD_STDIO
- #include "glplib.h"
- /***********************************************************************
- * NAME
- *
- * xfopen - open a stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * XFILE *xfopen(const char *fname, const char *mode);
- *
- * DESCRIPTION
- *
- * The routine xfopen opens the file whose name is a string pointed to
- * by fname and associates a stream with it.
- *
- * The parameter mode points to a string, which indicates the open mode
- * and should be one of the following:
- *
- * "r" open text file for reading;
- * "w" truncate to zero length or create text file for writing;
- * "rb" open binary file for reading;
- * "wb" truncate to zero length or create binary file for writing.
- *
- * RETURNS
- *
- * The routine xfopen returns a pointer to the object controlling the
- * stream. If the open operation fails, xfopen returns NULL. */
- static void *c_fopen(const char *fname, const char *mode);
- static void *z_fopen(const char *fname, const char *mode);
- static int is_gz_file(const char *fname)
- { char *ext = strrchr(fname, '.');
- return ext != NULL && strcmp(ext, ".gz") == 0;
- }
- XFILE *xfopen(const char *fname, const char *mode)
- { LIBENV *env = lib_link_env();
- XFILE *fp;
- int type;
- void *fh;
- if (!is_gz_file(fname))
- { type = FH_FILE;
- fh = c_fopen(fname, mode);
- }
- else
- { type = FH_ZLIB;
- fh = z_fopen(fname, mode);
- }
- if (fh == NULL)
- { fp = NULL;
- goto done;
- }
- fp = xmalloc(sizeof(XFILE));
- fp->type = type;
- fp->fh = fh;
- fp->prev = NULL;
- fp->next = env->file_ptr;
- if (fp->next != NULL) fp->next->prev = fp;
- env->file_ptr = fp;
- done: return fp;
- }
- /***********************************************************************
- * NAME
- *
- * xfgetc - read character from the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xfgetc(XFILE *fp);
- *
- * DESCRIPTION
- *
- * If the end-of-file indicator for the input stream pointed to by fp
- * is not set and a next character is present, the routine xfgetc
- * obtains that character as an unsigned char converted to an int and
- * advances the associated file position indicator for the stream (if
- * defined).
- *
- * RETURNS
- *
- * If the end-of-file indicator for the stream is set, or if the
- * stream is at end-of-file, the end-of-file indicator for the stream
- * is set and the routine xfgetc returns XEOF. Otherwise, the routine
- * xfgetc returns the next character from the input stream pointed to
- * by fp. If a read error occurs, the error indicator for the stream is
- * set and the xfgetc routine returns XEOF.
- *
- * Note: An end-of-file and a read error can be distinguished by use of
- * the routines xfeof and xferror. */
- static int c_fgetc(void *fh);
- static int z_fgetc(void *fh);
- int xfgetc(XFILE *fp)
- { int c;
- switch (fp->type)
- { case FH_FILE:
- c = c_fgetc(fp->fh);
- break;
- case FH_ZLIB:
- c = z_fgetc(fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- return c;
- }
- /***********************************************************************
- * NAME
- *
- * xfputc - write character to the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xfputc(int c, XFILE *fp);
- *
- * DESCRIPTION
- *
- * The routine xfputc writes the character specified by c (converted
- * to an unsigned char) to the output stream pointed to by fp, at the
- * position indicated by the associated file position indicator (if
- * defined), and advances the indicator appropriately.
- *
- * RETURNS
- *
- * The routine xfputc returns the character written. If a write error
- * occurs, the error indicator for the stream is set and xfputc returns
- * XEOF. */
- static int c_fputc(int c, void *fh);
- static int z_fputc(int c, void *fh);
- int xfputc(int c, XFILE *fp)
- { switch (fp->type)
- { case FH_FILE:
- c = c_fputc(c, fp->fh);
- break;
- case FH_ZLIB:
- c = z_fputc(c, fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- return c;
- }
- /***********************************************************************
- * NAME
- *
- * xferror - test error indicator for the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xferror(XFILE *fp);
- *
- * DESCRIPTION
- *
- * The routine xferror tests the error indicator for the stream
- * pointed to by fp.
- *
- * RETURNS
- *
- * The routine xferror returns non-zero if and only if the error
- * indicator is set for the stream. */
- static int c_ferror(void *fh);
- static int z_ferror(void *fh);
- int xferror(XFILE *fp)
- { int ret;
- switch (fp->type)
- { case FH_FILE:
- ret = c_ferror(fp->fh);
- break;
- case FH_ZLIB:
- ret = z_ferror(fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- return ret;
- }
- /***********************************************************************
- * NAME
- *
- * xfeof - test end-of-file indicator for the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xfeof(XFILE *fp);
- *
- * DESCRIPTION
- *
- * The routine xfeof tests the end-of-file indicator for the stream
- * pointed to by fp.
- *
- * RETURNS
- *
- * The routine xfeof returns non-zero if and only if the end-of-file
- * indicator is set for the stream. */
- static int c_feof(void *fh);
- static int z_feof(void *fh);
- int xfeof(XFILE *fp)
- { int ret;
- switch (fp->type)
- { case FH_FILE:
- ret = c_feof(fp->fh);
- break;
- case FH_ZLIB:
- ret = z_feof(fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- return ret;
- }
- /***********************************************************************
- * NAME
- *
- * xfflush - flush the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xfflush(XFILE *fp);
- *
- * DESCRIPTION
- *
- * The routine xfflush causes any unwritten data for the output stream
- * pointed to by fp to be written to the associated file.
- *
- * RETURNS
- *
- * The routine xfflush returns zero if the stream was successfully
- * flushed. Otherwise, xfflush sets the error indicator for the stream
- * and returns XEOF. */
- static int c_fflush(void *fh);
- static int z_fflush(void *fh);
- int xfflush(XFILE *fp)
- { int ret;
- switch (fp->type)
- { case FH_FILE:
- ret = c_fflush(fp->fh);
- break;
- case FH_ZLIB:
- ret = z_fflush(fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- return ret;
- }
- /***********************************************************************
- * NAME
- *
- * xfclose - close the stream
- *
- * SYNOPSIS
- *
- * #include "glplib.h"
- * int xfclose(XFILE *fp);
- *
- * DESCRIPTION
- *
- * A successful call to the routine xfclose causes the stream pointed
- * to by fp to be flushed and the associated file to be closed. Whether
- * or not the call succeeds, the stream is disassociated from the file.
- *
- * RETURNS
- *
- * The routine xfclose returns zero if the stream was successfully
- * closed, or XEOF if any errors were detected. */
- static int c_fclose(void *fh);
- static int z_fclose(void *fh);
- int xfclose(XFILE *fp)
- { LIBENV *env = lib_link_env();
- int ret;
- switch (fp->type)
- { case FH_FILE:
- ret = c_fclose(fp->fh);
- break;
- case FH_ZLIB:
- ret = z_fclose(fp->fh);
- break;
- default:
- xassert(fp != fp);
- }
- fp->type = 0xF00BAD;
- if (fp->prev == NULL)
- env->file_ptr = fp->next;
- else
- fp->prev->next = fp->next;
- if (fp->next == NULL)
- ;
- else
- fp->next->prev = fp->prev;
- xfree(fp);
- return ret;
- }
- /***********************************************************************
- * The following routines implement stream input/output based on the
- * standard C streams. */
- static void *c_fopen(const char *fname, const char *mode)
- { FILE *fh;
- fh = fopen(fname, mode);
- if (fh == NULL)
- lib_err_msg(strerror(errno));
- return fh;
- }
- static int c_fgetc(void *_fh)
- { FILE *fh = _fh;
- int c;
- if (ferror(fh) || feof(fh))
- { c = XEOF;
- goto done;
- }
- c = fgetc(fh);
- if (ferror(fh))
- { lib_err_msg(strerror(errno));
- c = XEOF;
- }
- else if (feof(fh))
- c = XEOF;
- else
- xassert(0x00 <= c && c <= 0xFF);
- done: return c;
- }
- static int c_fputc(int c, void *_fh)
- { FILE *fh = _fh;
- if (ferror(fh))
- { c = XEOF;
- goto done;
- }
- c = (unsigned char)c;
- fputc(c, fh);
- if (ferror(fh))
- { lib_err_msg(strerror(errno));
- c = XEOF;
- }
- done: return c;
- }
- static int c_ferror(void *_fh)
- { FILE *fh = _fh;
- return ferror(fh);
- }
- static int c_feof(void *_fh)
- { FILE *fh = _fh;
- return feof(fh);
- }
- static int c_fflush(void *_fh)
- { FILE *fh = _fh;
- int ret;
- ret = fflush(fh);
- if (ret != 0)
- { lib_err_msg(strerror(errno));
- ret = XEOF;
- }
- return ret;
- }
- static int c_fclose(void *_fh)
- { FILE *fh = _fh;
- int ret;
- ret = fclose(fh);
- if (ret != 0)
- { lib_err_msg(strerror(errno));
- ret = XEOF;
- }
- return ret;
- }
- /***********************************************************************
- * The following routines implement stream input/output based on the
- * zlib library, which provides processing .gz files "on the fly". */
- #ifndef HAVE_ZLIB
- static void *z_fopen(const char *fname, const char *mode)
- { xassert(fname == fname);
- xassert(mode == mode);
- lib_err_msg("Compressed files not supported");
- return NULL;
- }
- static int z_fgetc(void *fh)
- { xassert(fh != fh);
- return 0;
- }
- static int z_fputc(int c, void *fh)
- { xassert(c != c);
- xassert(fh != fh);
- return 0;
- }
- static int z_ferror(void *fh)
- { xassert(fh != fh);
- return 0;
- }
- static int z_feof(void *fh)
- { xassert(fh != fh);
- return 0;
- }
- static int z_fflush(void *fh)
- { xassert(fh != fh);
- return 0;
- }
- static int z_fclose(void *fh)
- { xassert(fh != fh);
- return 0;
- }
- #else
- #include <zlib.h>
- struct z_file
- { /* .gz file handle */
- gzFile file;
- /* pointer to .gz stream */
- int err;
- /* i/o error indicator */
- int eof;
- /* end-of-file indicator */
- };
- static void *z_fopen(const char *fname, const char *mode)
- { struct z_file *fh;
- gzFile file;
- if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
- mode = "rb";
- else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0)
- mode = "wb";
- else
- { lib_err_msg("Invalid open mode");
- fh = NULL;
- goto done;
- }
- file = gzopen(fname, mode);
- if (file == NULL)
- { lib_err_msg(strerror(errno));
- fh = NULL;
- goto done;
- }
- fh = xmalloc(sizeof(struct z_file));
- fh->file = file;
- fh->err = fh->eof = 0;
- done: return fh;
- }
- static int z_fgetc(void *_fh)
- { struct z_file *fh = _fh;
- int c;
- if (fh->err || fh->eof)
- { c = XEOF;
- goto done;
- }
- c = gzgetc(fh->file);
- if (c < 0)
- { int errnum;
- const char *msg;
- msg = gzerror(fh->file, &errnum);
- if (errnum == Z_STREAM_END)
- fh->eof = 1;
- else if (errnum == Z_ERRNO)
- { fh->err = 1;
- lib_err_msg(strerror(errno));
- }
- else
- { fh->err = 1;
- lib_err_msg(msg);
- }
- c = XEOF;
- }
- else
- xassert(0x00 <= c && c <= 0xFF);
- done: return c;
- }
- static int z_fputc(int c, void *_fh)
- { struct z_file *fh = _fh;
- if (fh->err)
- { c = XEOF;
- goto done;
- }
- c = (unsigned char)c;
- if (gzputc(fh->file, c) < 0)
- { int errnum;
- const char *msg;
- fh->err = 1;
- msg = gzerror(fh->file, &errnum);
- if (errnum == Z_ERRNO)
- lib_err_msg(strerror(errno));
- else
- lib_err_msg(msg);
- c = XEOF;
- }
- done: return c;
- }
- static int z_ferror(void *_fh)
- { struct z_file *fh = _fh;
- return fh->err;
- }
- static int z_feof(void *_fh)
- { struct z_file *fh = _fh;
- return fh->eof;
- }
- static int z_fflush(void *_fh)
- { struct z_file *fh = _fh;
- int ret;
- ret = gzflush(fh->file, Z_FINISH);
- if (ret == Z_OK)
- ret = 0;
- else
- { int errnum;
- const char *msg;
- fh->err = 1;
- msg = gzerror(fh->file, &errnum);
- if (errnum == Z_ERRNO)
- lib_err_msg(strerror(errno));
- else
- lib_err_msg(msg);
- ret = XEOF;
- }
- return ret;
- }
- static int z_fclose(void *_fh)
- { struct z_file *fh = _fh;
- gzclose(fh->file);
- xfree(fh);
- return 0;
- }
- #endif
- /* eof */