/* file.H: smart opening/closing files/pipes/urls */

#ifndef _XRML_FILE_H_
#define _XRML_FILE_H_

#include <stdio.h>
#include "memory.H"

namespace xrml {

// After opening, use old-style stdio on FILE* fp member (if non-null).
class file {
protected:
  // Parses a url into absolute url and target. Uses base_url to
  // convert a relative url into an absolute url. Results are in
  // 'url', 'target' and 'base_url' members.
  void make_url_target(const char *url, const char *base_url =0);

  // for indentation, to use with indent(), outdent() and newline()
  // member functions
  int spaces;

public:
  PoolDecl(file, "xrml::file")

  bool ispipe;		// true if file is a pipe
  bool istmpfile;	// true if file is a temporary file (downloaded url)
  char *name;		// file name (can be name of temporary file)
  char *url; 		// absolute url
  char *base_url;    	// base url
  char *target;		// url target (target=name in ...#name url)
  char *open_mode;	// "r", "w", ...
  bool error;		// true if not able to open the file
  FILE *fp;

  file() {
    name = open_mode = url = base_url = target = (char*)0;
    error = ispipe = istmpfile = false;
    spaces = 0;
    fp = (FILE*)NULL;
  }

  // Opens a local file with specified name.
  // Recognizes extensions .Z, .gz, .bz and .bz2 and calls comnpress, uncompress,
  // gzip, gunzip, bzip, bunzip, bzip2, bunzip2 as appropriate.
  // If first character is '|', '<' or '>', a pipe is opened to/from the command
  // following the '|', '<' or '>'. '|', '<' and '>' behave the same: the direction
  // of the pipe is determined solely by the open_mode.
  // If ext is not null, the file is opened as if it would have this extension.
  FILE *open(const char *filename, const char *open_mode, const char *ext =0);

  // Opens the specified url, retrieving it to a temporary file using wget if it 
  // is not a local file. If 'url' is a relative url, 'base_url' (if non-null) 
  // is used to convert it into and absolute url.
  FILE *openFromURL(const char *url, const char *base_url =0);

  // makes a fake file handle for the specified FILE *
  FILE *open(const char *filename, char *open_mode, FILE *fp, const bool ispipe);

  // Closes the file. If it is a temporary file (downloaded URL),
  // also schedules deletion of the file on exit of the program.
  void close(void);

  // Closes the file if fp is not null
  ~file();

  // indented output:
  // increase indentation
  inline void indent(void)  { spaces += 2; }

  // decrease indentation
  inline void outdent(void) { spaces -= 2; }

  // start indented new line
  inline void newline(void)
  {
    putc('\n', fp);
    for (int i=0; i<spaces; i++)
      putc(' ', fp);
  }

  // fprintf() replacement for file handles
  int printf(const char* format, ...);
};

} // namespace xrml

#endif /*_XRML_FILE_H_*/
