
/* ldf.c */

/* This file provides the function read_ldf() to read and return a line
 * of data from the library data file.  When necessary, read_ldf() first
 * opens the file.  It reads one line of data into a buffer provided by
 * the caller and returns zero if no line is available to read
 * (otherwise it returns a pointer to the buffer).  The line it reads
 * into the buffer always ends in a newline; otherwise, read_ldf()
 * returns zero.
 *
 * The caller must supply a buffer (at least) WIDTH_DATA+2 bytes wide.
 *
 * This file also provides the function rewind_ldf() to rewind the
 * library data file to its beginning.  The rewind_ldf() behaves well
 * whether the file marker is at file's beginning, at file's end, or
 * somewhere between.  It even behaves well if the data file is not open
 * yet or if no data file is even available.  Thus it is safe to
 * rewind_ldf() any time.
 *
 * The purpose of this file is to isolate from the rest of the program
 * the details of opening and reading a library data file which may or
 * may not be compressed and whose identity may occasionally have been
 * specified in a command-line option.  The rest of the program need
 * only know to call read_ldf() and rewind_ldf() when lines of library
 * data are wanted.  How the lines are interpreted is naturally up to
 * the caller.
 *
 */

#include "ldf.h"
#include "argp.h"
#include "gen.h"
#include <zlib.h>

enum isopen { GZ_FILE = 1, CLEAR_FILE };

static enum isopen isopen = 0;
static gzFile     *gzfile    ;
static FILE       *file      ;
static int         eof    = 0;

char *read_ldf( char *const buf ) {

  char *ret = 0;
  if ( eof ) return ret;

  if ( !isopen ) {
    char *filename_gz    = DATA_FILE_GZ;
    char *filename_clear = DATA_FILE   ;
    if ( opt.data_file_gz || opt.data_file ) {
      filename_gz    = opt.data_file_gz ? opt.data_file_gz : 0;
      filename_clear = opt.data_file    ? opt.data_file    : 0;
    }
    if      (( file   = fopen ( filename_clear, "r" ) ))
      isopen = CLEAR_FILE;
    else if (( gzfile = gzopen( filename_gz   , "r" ) ))
      isopen = GZ_FILE   ;
    else error(
      EACCES, 0,
      "cannot find and open the library data file"
    );
  }

  switch ( isopen ) {
    case GZ_FILE   : ret = gzgets( gzfile, buf, WIDTH_DATA+2 ); break;
    case CLEAR_FILE: ret = fgets ( buf, WIDTH_DATA+2, file   ); break;
    default: error(
      EPERM, 0,
      "impossible, ldf.c read_ldf()"
    );
  }

  if (  ret && buf[ strlen(buf) - 1 ] != '\n' ) ret = 0;
  if ( !ret                                   ) eof = 1;
  return ret;

}

void rewind_ldf( void ) {
  switch ( isopen ) {
    case GZ_FILE   : gzrewind( gzfile ); break;
    case CLEAR_FILE: rewind  ( file   ); break;
  }
  eof = 0;
}

