text: /* 
   * @HEADER
   *
   * ***********************************************************************
   *
   *  Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring
   *                  Copyright 2012 Sandia Corporation
   *
   * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
   * the U.S. Government retains certain rights in this software.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are
   * met:
   *
   * 1. Redistributions of source code must retain the above copyright
   * notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * 3. Neither the name of the Corporation nor the names of the
   * contributors may be used to endorse or promote products derived from
   * this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * Questions? Contact Karen Devine	kddevin@sandia.gov
   *                    Erik Boman	egboman@sandia.gov
   *
   * ***********************************************************************
   *
   * @HEADER
   */
  
  #include <stdarg.h>
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  
  #include "dr_const.h"
  #include "dr_compress_const.h"
  #include "dr_util_const.h"
  
  #ifdef __cplusplus
  /* if C++, define the rest of this header file as extern C */
  extern "C" {
  #endif
  
  #define BUFF_SIZE 3*1024*1024
  #define FILE_NAME_SIZE 256
  #define EXTENSION_SIZE 4
  
  #ifndef __USE_ISOC99
  int vfscanf(FILE * stream, const char * format,
                va_list arg);
  int vscanf(const char * format, va_list arg);
  int vsscanf(const char * s, const char * format,
  	    va_list arg);
  #endif /* __USE_ISOC99 */
  
  ZOLTAN_FILE* ZOLTAN_FILE_open(const char *path, const char *mode, const ZOLTAN_FILETYPE type)
  {
    ZOLTAN_FILE* file;
    char truemode[10];
    char filename[FILE_NAME_SIZE+EXTENSION_SIZE+1];
    int error = 1;
    int i;
  
    file = (ZOLTAN_FILE*) malloc(sizeof(ZOLTAN_FILE));
    if (file == NULL) return (NULL);
  
    file->type = type;
    file->pos = -1;
    file->size = 0;
  
    if (type != STANDARD) {
      if (!strstr(mode, "b"))
        sprintf(truemode, "%sb", mode);
      else
        strcpy(truemode, mode);
    }
  
    strncpy (filename, path, FILE_NAME_SIZE);
    for (i=0; (error != 0) && (i <2) ; ++i) {
  
      if (i == 0) { /* Try the classical compressed version */
        char append[EXTENSION_SIZE+1];
        switch (type) {
  #ifdef ZOLTAN_GZIP
        case GZIP:
  	strncpy (append, ".gz", EXTENSION_SIZE);
  	break;
  #endif
  #ifdef ZOLTAN_BZ2
        case BZIP2:
  	strncpy (append, ".bz2", EXTENSION_SIZE);
  	break;
  #endif
  #ifdef ZOLTAN_LZMA
        case LZMA:
  	strncpy (append, ".lz", EXTENSION_SIZE);
  	break;
  #endif
        default:
  	append[0] = '\0';
  	break;
        }
        strncat(filename, append, EXTENSION_SIZE);
      }
      else
        strncpy(filename, path, FILE_NAME_SIZE);
  
      switch (type) {
      case STANDARD:
        file->strm.fileunc = fopen(filename, mode);
        error = (file->strm.fileunc == NULL);
        break;
  #ifdef ZOLTAN_GZIP
      case GZIP:
        file->strm.filegz = gzopen(filename, truemode);
        error = (file->strm.filegz == NULL);
        break;
  #endif
  #ifdef ZOLTAN_BZ2
      case BZIP2:
        file->strm.filebz2 = BZ2_bzopen(filename, truemode);
        error = (file->strm.filebz2 == NULL);
        break;
  #endif
  #ifdef ZOLTAN_LZMA
      case LZMA:
        break;
  #endif
      default:
        break;
      }
    }
  
    if (error) {
      safe_free((void **)(void *) &file);
      return (NULL);
    }
  
    if (type != STANDARD) {
      file->buffer = (char*) malloc(BUFF_SIZE);
      if (file->buffer == NULL) {
        safe_free((void **)(void *) &file);
        return (NULL);
      }
    }
  
    return (file);
  }
  
  
  ssize_t ZOLTAN_FILE_read(char* ptr, size_t size, size_t nitems, ZOLTAN_FILE *file)
  {
    int toread = 0;
    int nbrdone = 0;
  
    if (file->type == STANDARD)
      return fread(ptr, size, nitems, file->strm.fileunc);
  
    toread = nitems;
    do {
      int tocpy = 0;
  
      tocpy = MIN(file->size - file->pos, toread);
      if ((tocpy > 0) && (file->pos >= 0)) {
        memcpy (ptr + nbrdone, file->buffer + file->pos, tocpy);
        file->pos += tocpy;
        toread -= tocpy;
        nbrdone += tocpy;
      }
      else {
        switch(file->type) {
  #ifdef ZOLTAN_GZIP
        case GZIP:
  	file->size = gzread(file->strm.filegz, file->buffer, BUFF_SIZE);
  	break;
  #endif
        default:
  	return (-1);
        }
        if (file->size < BUFF_SIZE)    /* Nothing else to read on next call */
  	toread = MIN(file->size, toread);
        if (file->size <= 0)
  	return (nbrdone);
        file->pos = 0;
      }
    } while (toread);
  
    return (nbrdone);
  }
  
  char* ZOLTAN_FILE_gets(char * buf, int len, ZOLTAN_FILE* file)
  {
    ssize_t size;
    char * end = NULL;
    ssize_t offset = 0;
  
    if (file->type == STANDARD) return (fgets(buf, len, file->strm.fileunc));
  
    if ((file->pos >= 0) &&( file->size > 0))
      offset = file->size - file->pos;
  
    if (offset > 0) {
      end = (char *) memchr(file->buffer + file->pos, '\n', MIN(offset, len - 1));
  
    }
    if (end != NULL) {          /* End of line found */
      size = end - (file->buffer + file->pos) + 1;
      memcpy (buf, file->buffer + file->pos, size);
      buf[size] = '\0';
      file->pos += size;
      return (buf);
    }
    /* No new line */
    size = ZOLTAN_FILE_read(buf, 1, len - 1, file);
    if (size == 0)
      return (NULL);
    buf[size] = '\0';
    end = (char *) memchr(buf, '\n', size);
    if (end == NULL) {
      return (buf);
    }
    end[1] = '\0';
    file->pos = (end-buf) - offset + 1;
    return (buf);
  }
  
  
  /* int ZOLTAN_FILE_putc(int c, ZOLTAN_FILE file) */
  /* { */
  /*   switch (file.type) { */
  /*   case STANDARD: */
  /*     return (fputc(c, file.fileunc)); */
  /* #ifdef ZOLTAN_GZIP */
  /*   case GZIP: */
  /*     return (gzputc(file.filegz, c)); */
  /* #endif */
  /*   default: */
  /*     break; */
  /*   } */
  /*   return (0); */
  /* } */
  
  int ZOLTAN_FILE_getc(ZOLTAN_FILE* file)
  {
    int read;
    if (file->type == STANDARD)
      return (fgetc(file->strm.fileunc));
    if (ZOLTAN_FILE_read((char*)&read, 1, 1, file) == 0)
      return (EOF);
    return (read);
  }
  
  int ZOLTAN_FILE_ungetc(int c, ZOLTAN_FILE* file)
  {
    if (file->type == STANDARD)
      return (ungetc(c, file->strm.fileunc));
  
    file->pos --;
    if (file->pos < 0) {
      file->size = 0;
  #ifdef ZOLTAN_GZIP
      if (file->type == GZIP)
        return (gzungetc(c, file->strm.filegz));
  #endif
    }
  
    file->buffer[file->pos] = (char)c;
    return (c);
  }
  
  int ZOLTAN_FILE_flush(ZOLTAN_FILE* file)
  {
    switch (file->type) {
    case STANDARD:
      return (fflush(file->strm.fileunc));
  #ifdef ZOLTAN_GZIP
    case GZIP:
      return (gzflush(file->strm.filegz, Z_SYNC_FLUSH));
  #endif
    default:
      break;
    }
    return (0);
  }
  
  int ZOLTAN_FILE_close(ZOLTAN_FILE* file)
  {
    int retval = 0;
  
    if (file == NULL)
      return (0);
    if (file->type == STANDARD)
      retval = fclose(file->strm.fileunc);
    else {
      switch (file->type) {
  #ifdef ZOLTAN_GZIP
      case GZIP:
        retval = gzclose(file->strm.filegz);
  #endif
      default:
        retval = 1;
        break;
      }
      safe_free((void **)(void *) (&file->buffer));
    }
    safe_free((void **)(void *) &file);
    return (retval);
  }
  
  void ZOLTAN_FILE_rewind(ZOLTAN_FILE* file)
  {
    switch (file->type) {
    case STANDARD:
      rewind(file->strm.fileunc);
      return;
  #ifdef ZOLTAN_GZIP
    case GZIP:
      gzrewind(file->strm.filegz);
      file->pos = -1;
      return;
  #endif
    default:
      break;
    }
  }
  
  /*** Implemented as a macro as "vfscanf" or "vsscanf" are C99 only ***/
  int ZOLTAN_FILE_scanf (ZOLTAN_FILE*  stream, const char *  format, ... )
  {
    int retval = 0;
    va_list argp;
  
    va_start(argp, format);
    if (stream->type == STANDARD) {
      retval = (vfscanf(stream->strm.fileunc, format, argp));
    }
    else {
      char buff[1024];
      if (ZOLTAN_FILE_gets(buff, 1024, (stream)) != NULL)
        retval = vsscanf(buff, format, argp);
    }
    va_end(argp);
    return (retval);
  }
  
  
  
  #ifdef __cplusplus
  } /* closing bracket for extern "C" */
  #endif
  