/*
* IRE - text file routines, loading and indexing thru' VFS layer
*/
#define NO_FORTIFY // Disable FORTIFY here (for speed)
#include <stdio.h>
#include <stdlib.h>
#include <allegro.h>
#include <string.h>
#include "textfile.h"
#include "loadfile.h"
#include "ithelib.h"
#define FUDGE_CHARACTER -2 // This is for string munging
static void fix_quotes(char *line);
static void unfix_quotes(char *line);
// set values to reasonable defaults
void TF_init(struct TF_S *s)
{
if(!s)
return;
s->size=0;
s->lines=0;
s->linewords=0;
s->block=NULL;
s->line=NULL;
s->lineword=NULL;
}
// free memory if necessary and set to defaults
void TF_term(struct TF_S *s)
{
if(s->size)
{
if(s->block)
free(s->block);
if(s->lineword)
free(s->lineword);
s->size=0;
}
if(s->lines)
{
if(s->line)
free(s->line);
s->lines=0;
}
}
// open file, alloc memory and index by line
void TF_load(struct TF_S *s, char *filename)
{
int ctr,current;
char fn[1024];
IFILE *fp;
if(!loadfile(filename,fn))
ithe_panic("Could not open text file:",filename);
fp=iopen(fn); // Open file
s->size = ifilelength(fp);
s->block = (char *)calloc(1,s->size+1); // Alloc memory for block, and a NULL
iread((unsigned char *)s->block,s->size,fp); // Read the file into block
iclose(fp); // Finished
s->lines = 1; // Count Carriage Returns
for(ctr = 0;ctr < s->size;ctr++)
if(s->block[ctr] == '\n') // Found one
s->lines++;
// We now know how many lines there are, so allocate the line index
s->line = (char **)calloc(s->lines,sizeof(char *));
// Now we go through the lines indexing them.
current = 0; // First line
s->line[0] = s->block; // This is the first line
for(ctr = 0;ctr < s->size;ctr++)
if(s->block[ctr] == '\n') // Found a line break
{
s->block[ctr] = 0; // End the string
// If we've got an MSDOS-style CR/LF format
if(ctr>0)
if(s->block[ctr-1] == 13)
s->block[ctr-1]=0; // Kill it
s->line[++current] = &s->block[ctr+1]; // This is the next line
}
}
// Split loaded file into words
void TF_splitwords(struct TF_S *s, char comment)
{
int ctr,ctr2,len,word,maxwords;
char *cptr;
if(!s)
return;
if(s->linewords)
return;
// Allocate the line word index
s->linewords = (int *)calloc(s->lines,sizeof(int *));
s->lineword = (char ***)calloc(s->lines,sizeof(char **));
// Now we go through the lines indexing them.
for(ctr = 0;ctr < s->lines;ctr++)
{
// Smash any comments
cptr=strchr(s->line[ctr],comment);
if(cptr)
*cptr=0;
fix_quotes(s->line[ctr]);
// Count number of words in the line
len=strcount(s->line[ctr]);
s->linewords[ctr]=len;
if(!len)
{
s->lineword[ctr]=NULL;
continue; // Round again
}
// Reserve space for at least 10 words (parser expects NULL for checking)
maxwords=16;
if(len>16)
maxwords=len;
s->lineword[ctr]=calloc(maxwords,sizeof(char **));
// Find the gaps between each word
cptr=s->line[ctr];
word=0;
do
{
if(*cptr == ' ')
cptr++;
else
{
s->lineword[ctr][word++]=cptr;
cptr=strchr(cptr,' ');
if(cptr)
*cptr++=0;
else
break; // Found the end
}
} while(*cptr);
// Fix the quotes
for(ctr2=0;ctr2<word;ctr2++)
unfix_quotes(s->lineword[ctr][ctr2]);
}
}
// Turn all spaces inside quotes to solid mass of guck for parameter system
static void fix_quotes(char *line)
{
char *p,inquote;
inquote=0;
for(p=line;*p;p++)
{
if(*p == '\"')
inquote=!inquote;
if(inquote && isxspace(*p))
*p=FUDGE_CHARACTER;
}
}
// Undo the operation of the previous function
void unfix_quotes(char *line)
{
char *p;
do
{
p=strchr(line,FUDGE_CHARACTER);
if(p)
*p=' ';
} while(p);
}