/*
   File:        inout.h
   Authors:     Andrew W. Moore
   Created:     Wed Jun  5 17:31:14 EDT 2002
   Description: Header for Input/Output Routines

   Copyright 2002, Andrew W. Moore
*/


#ifndef INOUT
#define INOUT

#include "amut.h"
#include "namer.h"
#include "saarray.h"

/* inout is a way of making the process of reading and writing Auton data
   structures to files extremely methodical. There is still some boring
   work needed...just as with the mk_copy_xxx functions and fprintf_xxx
   functions you now need to write

     void out_xxx(FILE *s)
     xxx *mk_in_xxx(inout *io)

   functions. But they are remarkably trivial to write. Here's an example.

   Suppose your structure is a confit, defined thus (you don't need
   to know what a confit is for)...

typedef struct confit
{
  int findex;
  int other;
  ivec *pindexes;
  regout *r1;
  regout *r2;
} confit;

   Then the loading function is just...

confit *mk_in_confit(inout *io)
{
  confit *nu = AM_MALLOC(confit);
  io_check_begin(io,"confit");

  nu -> findex = in_int(io);
  nu -> other = in_int(io);
  nu -> pindexes = mk_in_ivec(io);
  nu -> r1 = mk_in_regout(io);
  nu -> r2 = mk_in_regout(io);

  io_check_end(io,"confit");
  return nu;
}

And the saving function is just...

void out_confit(FILE *s,confit *x)
{
  io_begin(s,"confit");

  out_int(s,x->findex);
  out_int(s,x->other);
  out_ivec(s,x->pindexes);
  out_regout(s,x->r1);
  out_regout(s,x->r2);

  io_end(s,"confit");
}

As you see, the functions are boring to write (though Andrew uses
nifty emacs keyboard macros to auto-write them) but there's little
room for weird parsing bugs.

When you want to load something (e.g. a confit) from a file (e.g. called
confit.txt), you can just do...

inout *io = mk_inout("confit.txt");
confit *c = mk_in_confit(io);
:
:

If there's an error reading the file, a useful error message,
  telling you the line and filename, is given.

The format is XMLesque. It's all ASCII and the parser is smart enough
to not get confused by control-M's and all those other weird line-ending
things that crop up between linux vs mac vs windows.
*/

typedef struct inout
{
  char *filename;
  FILE *s;
  string_array *tokens;
  int next_toknum;
  
  int num_tokens_so_far;
  int next_report;
} inout;

char *mk_in_string(inout *io);

void out_string(FILE *s,char *string);

string_array *mk_in_string_array(inout *io);
sa_array *mk_in_sa_array( inout *io);

void out_string_array(FILE *s,string_array *sa);
void out_sa_array( FILE *s, sa_array *saa);

dyv *mk_in_dyv(inout *io);

ivec *mk_in_ivec(inout *io);

void out_dyv(FILE *s,dyv *x);

void out_ivec(FILE *s,ivec *x);

dyv_array *mk_in_dyv_array(inout *io);

void out_dyv_array(FILE *s,dyv_array *a);

ivec_array *mk_in_ivec_array(inout *io);

void out_ivec_array(FILE *s,ivec_array *a);

char *mk_begin_name(char *name);

char *mk_end_name(char *name);

void io_check(inout *io,char *expected_string);

void io_check_begin(inout *io,char *name);

void io_begin(FILE *s,char *name);

void io_end(FILE *s,char *name);

void io_check_end(inout *io,char *name);

int in_int(inout *io);

double in_double(inout *io);

bool in_bool(inout *io);

void out_bool(FILE *s,bool b);

void out_int(FILE *s,int x);

void out_double(FILE *s,double x);

inout *mk_inout(char *filename);

void free_inout(inout *x);

void fprintf_inout(FILE *s,char *m1,inout *x,char *m2);

void pinout(inout *x);

inout *mk_copy_inout(inout *old);

namer *mk_in_namer(inout *io);

void out_namer(FILE *s,namer *x);

void out_dym(FILE *s,dym *x);

dym *mk_in_dym(inout *io);

#endif /* #ifndef INOUT */
