TabText
The routines in TabText allow you to acquire a lines of text (terminated by \r or \n from a file, and then parse tab-delimited fields within the line. The input file is specificed by a FILE * pointer, and the file should be opened prior to calling the TabText routines.
Your program is responsible for allocating a LineBuffer to hold the line of data, and for disposing of the LineBuffer when no longer needed.
TabTable Source Code
Located in: svn+ssh://houptlab.org/svnroot/XcodeOOKernal/Tables
File Format
Tabtext assumes the following ascii text file format:
Line 1 Field 1 \t Field 2 \t Field 3 \t … Line 1 Field n \r
Line 2 Field 1 \t Field 2 \t Field 3 \t … Line 2 Field n \r
…
Line n Field 1 \t Field 2 \t Field 3 \t … Line n Field n \r
Note that lines can be terminated by \r or \n or \r\n or the end of the file.
Example Code
- (BOOL)readFile:(NSString *)filename returnError:(NSMutableString *)errorString
{
unsigned long i;
unsigned long num_lines, num_rows, lines_to_skip;
unsigned long row,column;
FILE *fp;
[errorString setString:@"no error"];
fp = fopen([filename cStringUsingEncoding:NSASCIIStringEncoding],"r");
// set up a line buffer
LineBuffer *line = NewLineBuffer(1000);
// how many lines in the file
num_lines = CountLinesInFile(line,fp);
// count lines rewinds the file, so we're back at the beginning..
lines_to_skip = NUM_HEADER_LINES;
num_rows = num_lines – lines_to_skip;
// skip the header lines, if they exist
for (i=0;i<lines_to_skip;i++) GetNextLine(line,fp);
// read in all the rows and columns
column = 0;
for(row=0;row<num_rows;row++) {
if (GetNextLine(line,fp)) {
while (GetNextTabField(line, tabtext)) {
SetRowColumnText(row,column,tabtext);
column++;
}
}
}
// all the rows have been read in
// done reading from the file, so dispose of file stuff
fclose(fp);
DisposeLineBuffer(line);
return(TRUE);
}
LineBuffer data structure
typedef struct {
unsigned long max; // maximum size of the line (i.e. size of buffer pointed to by text)
char *text; // the buffer that contains the last line read from the file
char *textptr; // for internal use; a ptr to the start of the next tab field
char *textend; // for internal use; a pointer to the end of the line
unsigned long length; // the length of the line, ie. the number of characters that were read in from the file
char *buffer_ptr; // points to start of next line in a buffer -- initialized by SetBuffer
unsigned long buffer_size; // the total number of characters in the buffer -- initialized by SetBuffer
} LineBuffer;
Routines
LineBuffer *NewLineBuffer(unsigned long size);
uses malloc to allocate a LineBuffer, and malloc to allocate a buffer (lineBuffer->text) that is size bytes long.
void DisposeLineBuffer(LineBuffer *line);
uses free to dispose of the text buffer and the LineBuffer itself.
Boolean GetNextLine(LineBuffer *line,FILE *fp);
Reads characters from the file pointed to by fp, beginning at the current position of the file, until one of 3 end-of-line characters are encountered: \r or \n or \r\n or the end of the file (when feof(fp) is TRUE). The line is transferred to the text buffer of the line. The end of line character is replaced with a null to make a null terminated string.
Boolean GetNextTabField(LineBuffer *line, char *text);
Copies the next series of characters in line-text into text, terminating when either a tab character \t or the end of the line is encountered. Returns TRUE if a tab field is found, or FALSE if we have already incremented through the entire line. The internal variable line-textptr is updated to point to the beginning of the next tab field.
void ResetTabFields(LineBuffer *line);
Rewind the internal pointer, so that the next tab field returned by GetNextTabField is the first tabfield in the line. NB: this only rewinds the current line, not the whole file – use rewind(fp) for that.
unsigned long CountLinesInFile(LineBuffer *line,FILE *fp);
A utility routine to increment through the entire file just to count how many lines of text are in the file (i.e. how many lines are terminated by \r or \n. This routine DOES call rewind(fp) before returning, so fp points to the start of the file upon returning.
void SetBuffer(LineBuffer *line,char *buffer, unsigned long size);
Sets the internal variables line->buffer_ptr and buffer_size will start looking for complete lines starting at buffer_ptr buffer_ptr will be incremented to keep track of our position in the buffer
void RewindBuffer(LineBuffer *line,char *buffer);
resets the internal variable line->buffer_ptr, so we start searching for lines at the beginning of the buffer
Boolean GetNextLineInBuffer(LineBuffer *line,char *buffer);
get the next array of characters that are terminated by /r or /n or end-of-file and store them as a null-terminared string in line->text
unsigned long CountLinesInBuffer(LineBuffer *line,char *buffer,unsigned long size);
given a buffer of size characters, return the number of lines that are terminated by /r or /n. Calls SetBuffer and RewindBuffer on exit, so you are back at the beginning of the buffer