PageRenderTime 40ms CodeModel.GetById 17ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1/* glplib08.c (stream input/output) */
  2
  3/***********************************************************************
  4*  This code is part of GLPK (GNU Linear Programming Kit).
  5*
  6*  Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,
  7*  Department for Applied Informatics, Moscow Aviation Institute,
  8*  Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
  9*
 10*  GLPK is free software: you can redistribute it and/or modify it
 11*  under the terms of the GNU General Public License as published by
 12*  the Free Software Foundation, either version 3 of the License, or
 13*  (at your option) any later version.
 14*
 15*  GLPK is distributed in the hope that it will be useful, but WITHOUT
 16*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 17*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 18*  License for more details.
 19*
 20*  You should have received a copy of the GNU General Public License
 21*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
 22***********************************************************************/
 23
 24#define _GLPSTD_ERRNO
 25#define _GLPSTD_STDIO
 26#include "glplib.h"
 27
 28/***********************************************************************
 29*  NAME
 30*
 31*  xfopen - open a stream
 32*
 33*  SYNOPSIS
 34*
 35*  #include "glplib.h"
 36*  XFILE *xfopen(const char *fname, const char *mode);
 37*
 38*  DESCRIPTION
 39*
 40*  The routine xfopen opens the file whose name is a string pointed to
 41*  by fname and associates a stream with it.
 42*
 43*  The parameter mode points to a string, which indicates the open mode
 44*  and should be one of the following:
 45*
 46*  "r"   open text file for reading;
 47*  "w"   truncate to zero length or create text file for writing;
 48*  "rb"  open binary file for reading;
 49*  "wb"  truncate to zero length or create binary file for writing.
 50*
 51*  RETURNS
 52*
 53*  The routine xfopen returns a pointer to the object controlling the
 54*  stream. If the open operation fails, xfopen returns NULL. */
 55
 56static void *c_fopen(const char *fname, const char *mode);
 57static void *z_fopen(const char *fname, const char *mode);
 58
 59static int is_gz_file(const char *fname)
 60{     char *ext = strrchr(fname, '.');
 61      return ext != NULL && strcmp(ext, ".gz") == 0;
 62}
 63
 64XFILE *xfopen(const char *fname, const char *mode)
 65{     LIBENV *env = lib_link_env();
 66      XFILE *fp;
 67      int type;
 68      void *fh;
 69      if (!is_gz_file(fname))
 70      {  type = FH_FILE;
 71         fh = c_fopen(fname, mode);
 72      }
 73      else
 74      {  type = FH_ZLIB;
 75         fh = z_fopen(fname, mode);
 76      }
 77      if (fh == NULL)
 78      {  fp = NULL;
 79         goto done;
 80      }
 81      fp = xmalloc(sizeof(XFILE));
 82      fp->type = type;
 83      fp->fh = fh;
 84      fp->prev = NULL;
 85      fp->next = env->file_ptr;
 86      if (fp->next != NULL) fp->next->prev = fp;
 87      env->file_ptr = fp;
 88done: return fp;
 89}
 90
 91/***********************************************************************
 92*  NAME
 93*
 94*  xfgetc - read character from the stream
 95*
 96*  SYNOPSIS
 97*
 98*  #include "glplib.h"
 99*  int xfgetc(XFILE *fp);
100*
101*  DESCRIPTION
102*
103*  If the end-of-file indicator for the input stream pointed to by fp
104*  is not set and a next character is present, the routine xfgetc
105*  obtains that character as an unsigned char converted to an int and
106*  advances the associated file position indicator for the stream (if
107*  defined).
108*
109*  RETURNS
110*
111*  If the end-of-file indicator for the stream is set, or if the
112*  stream is at end-of-file, the end-of-file indicator for the stream
113*  is set and the routine xfgetc returns XEOF. Otherwise, the routine
114*  xfgetc returns the next character from the input stream pointed to
115*  by fp. If a read error occurs, the error indicator for the stream is
116*  set and the xfgetc routine returns XEOF.
117*
118*  Note: An end-of-file and a read error can be distinguished by use of
119*  the routines xfeof and xferror. */
120
121static int c_fgetc(void *fh);
122static int z_fgetc(void *fh);
123
124int xfgetc(XFILE *fp)
125{     int c;
126      switch (fp->type)
127      {  case FH_FILE:
128            c = c_fgetc(fp->fh);
129            break;
130         case FH_ZLIB:
131            c = z_fgetc(fp->fh);
132            break;
133         default:
134            xassert(fp != fp);
135      }
136      return c;
137}
138
139/***********************************************************************
140*  NAME
141*
142*  xfputc - write character to the stream
143*
144*  SYNOPSIS
145*
146*  #include "glplib.h"
147*  int xfputc(int c, XFILE *fp);
148*
149*  DESCRIPTION
150*
151*  The routine xfputc writes the character specified by c (converted
152*  to an unsigned char) to the output stream pointed to by fp, at the
153*  position indicated by the associated file position indicator (if
154*  defined), and advances the indicator appropriately.
155*
156*  RETURNS
157*
158*  The routine xfputc returns the character written. If a write error
159*  occurs, the error indicator for the stream is set and xfputc returns
160*  XEOF. */
161
162static int c_fputc(int c, void *fh);
163static int z_fputc(int c, void *fh);
164
165int xfputc(int c, XFILE *fp)
166{     switch (fp->type)
167      {  case FH_FILE:
168            c = c_fputc(c, fp->fh);
169            break;
170         case FH_ZLIB:
171            c = z_fputc(c, fp->fh);
172            break;
173         default:
174            xassert(fp != fp);
175      }
176      return c;
177}
178
179/***********************************************************************
180*  NAME
181*
182*  xferror - test error indicator for the stream
183*
184*  SYNOPSIS
185*
186*  #include "glplib.h"
187*  int xferror(XFILE *fp);
188*
189*  DESCRIPTION
190*
191*  The routine xferror tests the error indicator for the stream
192*  pointed to by fp.
193*
194*  RETURNS
195*
196*  The routine xferror returns non-zero if and only if the error
197*  indicator is set for the stream. */
198
199static int c_ferror(void *fh);
200static int z_ferror(void *fh);
201
202int xferror(XFILE *fp)
203{     int ret;
204      switch (fp->type)
205      {  case FH_FILE:
206            ret = c_ferror(fp->fh);
207            break;
208         case FH_ZLIB:
209            ret = z_ferror(fp->fh);
210            break;
211         default:
212            xassert(fp != fp);
213      }
214      return ret;
215}
216
217/***********************************************************************
218*  NAME
219*
220*  xfeof - test end-of-file indicator for the stream
221*
222*  SYNOPSIS
223*
224*  #include "glplib.h"
225*  int xfeof(XFILE *fp);
226*
227*  DESCRIPTION
228*
229*  The routine xfeof tests the end-of-file indicator for the stream
230*  pointed to by fp.
231*
232*  RETURNS
233*
234*  The routine xfeof returns non-zero if and only if the end-of-file
235*  indicator is set for the stream. */
236
237static int c_feof(void *fh);
238static int z_feof(void *fh);
239
240int xfeof(XFILE *fp)
241{     int ret;
242      switch (fp->type)
243      {  case FH_FILE:
244            ret = c_feof(fp->fh);
245            break;
246         case FH_ZLIB:
247            ret = z_feof(fp->fh);
248            break;
249         default:
250            xassert(fp != fp);
251      }
252      return ret;
253}
254
255/***********************************************************************
256*  NAME
257*
258*  xfflush - flush the stream
259*
260*  SYNOPSIS
261*
262*  #include "glplib.h"
263*  int xfflush(XFILE *fp);
264*
265*  DESCRIPTION
266*
267*  The routine xfflush causes any unwritten data for the output stream
268*  pointed to by fp to be written to the associated file.
269*
270*  RETURNS
271*
272*  The routine xfflush returns zero if the stream was successfully
273*  flushed. Otherwise, xfflush sets the error indicator for the stream
274*  and returns XEOF. */
275
276static int c_fflush(void *fh);
277static int z_fflush(void *fh);
278
279int xfflush(XFILE *fp)
280{     int ret;
281      switch (fp->type)
282      {  case FH_FILE:
283            ret = c_fflush(fp->fh);
284            break;
285         case FH_ZLIB:
286            ret = z_fflush(fp->fh);
287            break;
288         default:
289            xassert(fp != fp);
290      }
291      return ret;
292}
293
294/***********************************************************************
295*  NAME
296*
297*  xfclose - close the stream
298*
299*  SYNOPSIS
300*
301*  #include "glplib.h"
302*  int xfclose(XFILE *fp);
303*
304*  DESCRIPTION
305*
306*  A successful call to the routine xfclose causes the stream pointed
307*  to by fp to be flushed and the associated file to be closed. Whether
308*  or not the call succeeds, the stream is disassociated from the file.
309*
310*  RETURNS
311*
312*  The routine xfclose returns zero if the stream was successfully
313*  closed, or XEOF if any errors were detected. */
314
315static int c_fclose(void *fh);
316static int z_fclose(void *fh);
317
318int xfclose(XFILE *fp)
319{     LIBENV *env = lib_link_env();
320      int ret;
321      switch (fp->type)
322      {  case FH_FILE:
323            ret = c_fclose(fp->fh);
324            break;
325         case FH_ZLIB:
326            ret = z_fclose(fp->fh);
327            break;
328         default:
329            xassert(fp != fp);
330      }
331      fp->type = 0xF00BAD;
332      if (fp->prev == NULL)
333         env->file_ptr = fp->next;
334      else
335         fp->prev->next = fp->next;
336      if (fp->next == NULL)
337         ;
338      else
339         fp->next->prev = fp->prev;
340      xfree(fp);
341      return ret;
342}
343
344/***********************************************************************
345*  The following routines implement stream input/output based on the
346*  standard C streams. */
347
348static void *c_fopen(const char *fname, const char *mode)
349{     FILE *fh;
350      fh = fopen(fname, mode);
351      if (fh == NULL)
352         lib_err_msg(strerror(errno));
353      return fh;
354}
355
356static int c_fgetc(void *_fh)
357{     FILE *fh = _fh;
358      int c;
359      if (ferror(fh) || feof(fh))
360      {  c = XEOF;
361         goto done;
362      }
363      c = fgetc(fh);
364      if (ferror(fh))
365      {  lib_err_msg(strerror(errno));
366         c = XEOF;
367      }
368      else if (feof(fh))
369         c = XEOF;
370      else
371         xassert(0x00 <= c && c <= 0xFF);
372done: return c;
373}
374
375static int c_fputc(int c, void *_fh)
376{     FILE *fh = _fh;
377      if (ferror(fh))
378      {  c = XEOF;
379         goto done;
380      }
381      c = (unsigned char)c;
382      fputc(c, fh);
383      if (ferror(fh))
384      {  lib_err_msg(strerror(errno));
385         c = XEOF;
386      }
387done: return c;
388}
389
390static int c_ferror(void *_fh)
391{     FILE *fh = _fh;
392      return ferror(fh);
393}
394
395static int c_feof(void *_fh)
396{     FILE *fh = _fh;
397      return feof(fh);
398}
399
400static int c_fflush(void *_fh)
401{     FILE *fh = _fh;
402      int ret;
403      ret = fflush(fh);
404      if (ret != 0)
405      {  lib_err_msg(strerror(errno));
406         ret = XEOF;
407      }
408      return ret;
409}
410
411static int c_fclose(void *_fh)
412{     FILE *fh = _fh;
413      int ret;
414      ret = fclose(fh);
415      if (ret != 0)
416      {  lib_err_msg(strerror(errno));
417         ret = XEOF;
418      }
419      return ret;
420}
421
422/***********************************************************************
423*  The following routines implement stream input/output based on the
424*  zlib library, which provides processing .gz files "on the fly". */
425
426#ifndef HAVE_ZLIB
427
428static void *z_fopen(const char *fname, const char *mode)
429{     xassert(fname == fname);
430      xassert(mode == mode);
431      lib_err_msg("Compressed files not supported");
432      return NULL;
433}
434
435static int z_fgetc(void *fh)
436{     xassert(fh != fh);
437      return 0;
438}
439
440static int z_fputc(int c, void *fh)
441{     xassert(c != c);
442      xassert(fh != fh);
443      return 0;
444}
445
446static int z_ferror(void *fh)
447{     xassert(fh != fh);
448      return 0;
449}
450
451static int z_feof(void *fh)
452{     xassert(fh != fh);
453      return 0;
454}
455
456static int z_fflush(void *fh)
457{     xassert(fh != fh);
458      return 0;
459}
460
461static int z_fclose(void *fh)
462{     xassert(fh != fh);
463      return 0;
464}
465
466#else
467
468#include <zlib.h>
469
470struct z_file
471{     /* .gz file handle */
472      gzFile file;
473      /* pointer to .gz stream */
474      int err;
475      /* i/o error indicator */
476      int eof;
477      /* end-of-file indicator */
478};
479
480static void *z_fopen(const char *fname, const char *mode)
481{     struct z_file *fh;
482      gzFile file;
483      if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0)
484         mode = "rb";
485      else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0)
486         mode = "wb";
487      else
488      {  lib_err_msg("Invalid open mode");
489         fh = NULL;
490         goto done;
491      }
492      file = gzopen(fname, mode);
493      if (file == NULL)
494      {  lib_err_msg(strerror(errno));
495         fh = NULL;
496         goto done;
497      }
498      fh = xmalloc(sizeof(struct z_file));
499      fh->file = file;
500      fh->err = fh->eof = 0;
501done: return fh;
502}
503
504static int z_fgetc(void *_fh)
505{     struct z_file *fh = _fh;
506      int c;
507      if (fh->err || fh->eof)
508      {  c = XEOF;
509         goto done;
510      }
511      c = gzgetc(fh->file);
512      if (c < 0)
513      {  int errnum;
514         const char *msg;
515         msg = gzerror(fh->file, &errnum);
516         if (errnum == Z_STREAM_END)
517            fh->eof = 1;
518         else if (errnum == Z_ERRNO)
519         {  fh->err = 1;
520            lib_err_msg(strerror(errno));
521         }
522         else
523         {  fh->err = 1;
524            lib_err_msg(msg);
525         }
526         c = XEOF;
527      }
528      else
529         xassert(0x00 <= c && c <= 0xFF);
530done: return c;
531}
532
533static int z_fputc(int c, void *_fh)
534{     struct z_file *fh = _fh;
535      if (fh->err)
536      {  c = XEOF;
537         goto done;
538      }
539      c = (unsigned char)c;
540      if (gzputc(fh->file, c) < 0)
541      {  int errnum;
542         const char *msg;
543         fh->err = 1;
544         msg = gzerror(fh->file, &errnum);
545         if (errnum == Z_ERRNO)
546            lib_err_msg(strerror(errno));
547         else
548            lib_err_msg(msg);
549         c = XEOF;
550      }
551done: return c;
552}
553
554static int z_ferror(void *_fh)
555{     struct z_file *fh = _fh;
556      return fh->err;
557}
558
559static int z_feof(void *_fh)
560{     struct z_file *fh = _fh;
561      return fh->eof;
562}
563
564static int z_fflush(void *_fh)
565{     struct z_file *fh = _fh;
566      int ret;
567      ret = gzflush(fh->file, Z_FINISH);
568      if (ret == Z_OK)
569         ret = 0;
570      else
571      {  int errnum;
572         const char *msg;
573         fh->err = 1;
574         msg = gzerror(fh->file, &errnum);
575         if (errnum == Z_ERRNO)
576            lib_err_msg(strerror(errno));
577         else
578            lib_err_msg(msg);
579         ret = XEOF;
580      }
581      return ret;
582}
583
584static int z_fclose(void *_fh)
585{     struct z_file *fh = _fh;
586      gzclose(fh->file);
587      xfree(fh);
588      return 0;
589}
590
591#endif
592
593/* eof */