/* Steven Andrews, 3/30/97	*/
/* Basic data saving and loading routines	*/
/* See documentation called DiskIO doc */
/* Copyright 2003 by Steven Andrews.  Permission is granted
   for non-commercial use of and modifications to the code. */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "DiskIO.h"
#include "string2.h"

typedef struct pagestruct {
	float *x;
	struct pagestruct *next;} *page;

page allocpage(int n);
void freepages(page pptr);



page allocpage(int n) {
	page pptr;
	int i;

	pptr=(page) malloc(sizeof(struct pagestruct));
	if(!pptr) return NULL;
	pptr->next=NULL;
	pptr->x=(float *) calloc(n,sizeof(float));
	if(!pptr->x) {free(pptr);return NULL;}
	for(i=0;i<n;i++) pptr->x[i]=0;
	return pptr; }



void freepages(page pptr) {
	page pptrn;
	
	for(;pptr;pptr=pptrn) {
		pptrn=pptr->next;
		free(pptr->x);
		free(pptr); }
	return; }



int GetName(char **name,int *nmfre) {
	if(!name||!nmfre) return 6;
	*nmfre=0;
	if(!*name)	{
		*name=(char *) calloc(STRCHAR,sizeof(char));
		if(!*name) return 1;
		(*name)[0]=0;
		*nmfre=1; }
	if(!strlen(*name))	{
		fprintf(stderr,"Enter file name (or 'cancel'): ");
		scanf("%s",*name); }
	if(!strlen(*name)||!strcmp(*name,"cancel")) {
		if(*nmfre) {free(*name);*nmfre=0;}
		return 2; }
	return 0; }



int SaveData(float *a,int m,int n,char *name,int append) {
	FILE *fptr;
	int i,j,nmfre,er;
	char str[STRCHAR];
	
	er=GetName(&name,&nmfre);
	if(er) return er;
	if(!strcmp(name,"stdout")) fptr=stdout;
	else if(append==1) fptr=fopen(name,"a");
	else if(append==2) fptr=fopen(name,"w");
	else {
		fptr=fopen(name,"r");
		if(fptr) {
			fclose(fptr);
			fprintf(stderr,"File exists. Do you want to overwrite it? ");
			scanf("%s",str);
			if(str[0]!='y'&&str[0]!='Y') {
				if(nmfre) free(name);
				return 2;}}
		fptr=fopen(name,"w");}
	if(nmfre) free(name);
	if(!fptr) return 3;
	for(i=0;i<m&&!er;i++)	{
		for(j=0;j<n&&!er;j++)
			if(fprintf(fptr,"%f ",a[n*i+j])<0) er=3;
		if(fprintf(fptr,"\n")<0) er=3;	}
	if(fptr!=stdout) fclose(fptr);
	return er; }


int SaveData2(double *x,double **a,int m,int n,char *name,int append) {
	FILE *fptr;
	int i,j,nmfre,er;
	char str[STRCHAR];
	
	er=GetName(&name,&nmfre);
	if(er) return er;
	if(!strcmp(name,"stdout")) fptr=stdout;
	else if(append==1) fptr=fopen(name,"a");
	else if(append==2) fptr=fopen(name,"w");
	else {
		fptr=fopen(name,"r");
		if(fptr) {
			fclose(fptr);
			fprintf(stderr,"File exists. Do you want to overwrite it? ");
			scanf("%s",str);
			if(str[0]!='y'&&str[0]!='Y') {
				if(nmfre) free(name);
				return 2;}}
		fptr=fopen(name,"w");}
	if(nmfre) free(name);
	if(!fptr) return 3;
	for(i=0;i<m&&!er;i++)	{
		if(x)
			if(fprintf(fptr,"%g",x[i])<0) er=3;
		if(a)
			for(j=0;j<n && !er;j++)
				if(fprintf(fptr,"%s%g",(x || j>0)?" ":"",a[j][i])<0) er=3;
		if(fprintf(fptr,"\n")<0) er=3;	}
	if(fptr!=stdout) fclose(fptr);
	return er; }



int SaveString(char *s,char *name,int append) {
	FILE *fptr;
	int nmfre,er;
	char str[STRCHAR];
	
	er=GetName(&name,&nmfre);
	if(er) return er;
	if(!strcmp(name,"stdout")) fptr=stdout;
	else if(append==1) fptr=fopen(name,"a");
	else if(append==2) fptr=fopen(name,"w");
	else	{
		fptr=fopen(name,"r");
		if(fptr)	{
			fclose(fptr);
			fprintf(stderr,"File exists. Do you want to overwrite it? ");
			scanf("%s",str);
			if(str[0]!='y'&&str[0]!='Y') {
				if(nmfre) free(name);
				return 2;}}
		fptr=fopen(name,"w");}
	if(nmfre) free(name);
	if(!fptr) return 3;
	if(fprintf(fptr,"%s\n",s)<0) er=3;
	if(fptr!=stdout) fclose(fptr);
	return er; }



int LoadData(float *a,int n,char *name) {
	FILE *fptr;
	int i,nmfre,er;
	
	er=GetName(&name,&nmfre);
	if(er) return er;
	if(!strcmp(name,"stdin"))	fptr=stdin;
	else fptr=fopen(name,"r");
	if(nmfre) free(name);
	if(!fptr) return 5;
	for(i=0;i<n&&!er;i++)
		if(fscanf(fptr,"%f",&a[i])<1) er=4;
	if(fptr!=stdin) fclose(fptr);
	return er; }



int LoadData2(float **a,int *n,int *col,char *name,int skip) {
	FILE *fptr;
	char line[STRCHAR];
	int i,j,er,nmfre,itct;
	float *a2;
	page pptr,pptr1;

	*a=NULL;
	*n=*col=0;
	pptr=pptr1=NULL;
	fptr=NULL;
	er=GetName(&name,&nmfre);	
	if(er) return er;
	if(!strcmp(name,"stdin"))	fptr=stdin;
	else fptr=fopen(name,"r");
	if(nmfre) free(name);
	if(!fptr) return 5;
	for(i=0;i<=skip&&!er;i++)	er=!fgets(line,STRCHAR,fptr);
	if(er) {er=4;goto leave;}
	*col=wordcount(line);
	if(*col<1) {er=4;goto leave;}

	pptr=pptr1=allocpage(*col);
	if(!pptr) {er=1;goto leave;}
	*n=1;
	while(!er)	{				/* load data in pages */
		itct=strreadnf(line,*col,pptr->x,NULL);
		if(itct!=*col) {er=4;goto leave;}
		er=!fgets(line,STRCHAR,fptr);
		if(!er) {
			pptr=pptr->next=allocpage(*col);
			if(!pptr) {er=1;goto leave;}
			(*n)++; }}
	er=0;
	a2=*a=(float *) calloc(*n**col,sizeof(float));
	if(!a2) {er=1;goto leave;}
	for(pptr=pptr1,i=0;pptr&&i<*n**col;pptr=pptr->next)
		for(j=0;j<*col;j++)
			a2[i++]=pptr->x[j];
 leave:
	if(fptr&&fptr!=stdin) fclose(fptr);
	freepages(pptr1);
	return er; }



int LoadData3(float **a,int *n,int xcol,int ycol,char *name,int skip) {
	FILE *fptr;
	char line[STRCHAR],*chptr;
	int i,j,er,nmfre,ok;
	float *a2;
	page pptr1,pptr;

	*a=NULL;
	*n=0;
	pptr=pptr1=NULL;
	fptr=NULL;
	
	er=GetName(&name,&nmfre);	
	if(er) return er;
	if(!strcmp(name,"stdin"))	fptr=stdin;
	else fptr=fopen(name,"r");
	if(nmfre) free(name);
	if(!fptr) return 5;
	for(i=0;i<=skip&&!er;i++)	er=!fgets(line,STRCHAR,fptr);
	if(er) {er=4;goto leave;}
	pptr=pptr1=allocpage(2);
	if(!pptr) {er=1;goto leave;}
	*n=0;
	while(!er) {
		strchrreplace(line,',',' ');
		chptr=strnword1(line,xcol);
		if(chptr) ok=sscanf(chptr,"%f",&(pptr->x[0]));
		if(ok&&chptr) chptr=strnword1(line,ycol);
		if(ok&&chptr) ok=sscanf(chptr,"%f",&(pptr->x[1]));
		if(ok&&chptr) (*n)++;
		er=!fgets(line,STRCHAR,fptr);
		if(!er&&ok&&chptr) {
			pptr=pptr->next=allocpage(2);
			if(!pptr) {er=1;goto leave;}}}
	er=0;
	if(!*n) {er=4;goto leave;}
	a2=*a=(float *) calloc(*n*2,sizeof(float));
	if(!a2) {er=1;goto leave;}
	for(pptr=pptr1,i=0;pptr&&i<*n*2;pptr=pptr->next)
		for(j=0;j<2;j++)
			a2[i++]=pptr->x[j];
 leave:
	if(fptr&&fptr!=stdin) fclose(fptr);
	freepages(pptr1);
	return er; }



int KillData(char *name) {
	int er,nmfre;

	er=GetName(&name,&nmfre);
	if(er) return er;
	er=remove(name)?5:0;
	if(nmfre) free(name);
	return er; }


