Difference between revisions of "TabText"

From MagnetoWiki
Jump to navigation Jump to search
(Added source code links)
(Switched to Syntax Highlighting)
 
(3 intermediate revisions by 2 users not shown)
Line 7: Line 7:
 
Located in: svn+ssh://houptlab.org/svnroot/XcodeOOKernal/Tables
 
Located in: svn+ssh://houptlab.org/svnroot/XcodeOOKernal/Tables
  
[http://houptlab.org/xtechops/websvn/filedetails.php?repname=Houpt+Lab+Source+Code&path=%2FXcodeOOKernal%2FTables%2FTabText.h TabText.h]<br>
+
[{{SERVER}}/cortex/websvn/filedetails.php?repname=Houpt+Lab+Source+Code&path=%2FXcodeOOKernal%2FTables%2FTabText.h TabText.h]<br>
[http://houptlab.org/xtechops/websvn/filedetails.php?repname=Houpt+Lab+Source+Code&path=%2FXcodeOOKernal%2FTables%2FTabText.c TabText.c]
+
[{{SERVER}}/cortex/websvn/filedetails.php?repname=Houpt+Lab+Source+Code&path=%2FXcodeOOKernal%2FTables%2FTabText.c TabText.c]
 
 
  
 
== File Format ==
 
== File Format ==
Line 27: Line 26:
 
==Example Code==
 
==Example Code==
  
<tt>
+
<syntaxhighlight lang=objective-c>
 
 
 
- (BOOL)readFile:(NSString *)filename returnError:(NSMutableString *)errorString  
 
- (BOOL)readFile:(NSString *)filename returnError:(NSMutableString *)errorString  
 
 
 
{
 
{
:unsigned long i;
+
  unsigned long i;
  
:unsigned long num_lines, num_rows, lines_to_skip;
+
  unsigned long num_lines, num_rows, lines_to_skip;
  
:unsigned long row,column;
+
  unsigned long row,column;
  
:FILE *fp;
+
  FILE *fp;
 
 
:[errorString setString:@"no error"];
+
  [errorString setString:@"no error"];
 
 
:fp = fopen([filename cStringUsingEncoding:NSASCIIStringEncoding],"r");
+
  fp = fopen([filename cStringUsingEncoding:NSASCIIStringEncoding],"r");
 
 
:// set up a line buffer
+
  // set up a line buffer
  
:LineBuffer *line = NewLineBuffer(1000);
+
  LineBuffer *line = NewLineBuffer(1000);
 
 
:// how many lines in the file
+
  // how many lines in the file
  
:num_lines = CountLinesInFile(line,fp);  
+
  num_lines = CountLinesInFile(line,fp);  
  
:// count lines rewinds the file, so we're back at the beginning..
+
  // count lines rewinds the file, so we're back at the beginning..
  
:lines_to_skip = NUM_HEADER_LINES;
+
  lines_to_skip = NUM_HEADER_LINES;
  
:num_rows = num_lines – lines_to_skip;
+
  num_rows = num_lines – lines_to_skip;
 
 
:// skip the header lines, if they exist
+
  // skip the header lines, if they exist
  
:for (i=0;i<lines_to_skip;i++) GetNextLine(line,fp);  
+
  for (i=0;i<lines_to_skip;i++) GetNextLine(line,fp);  
 
 
:// read in all the rows and columns
+
  // read in all the rows and columns
  
:column = 0;
+
  column = 0;
  
:for(row=0;row<num_rows;row++) {
+
  for(row=0;row<num_rows;row++) {
  
::if (GetNextLine(line,fp)) {
+
    if (GetNextLine(line,fp)) {
  
:::while (GetNextTabField(line, tabtext)) {
+
      while (GetNextTabField(line, tabtext)) {
 
 
::::SetRowColumnText(row,column,tabtext);
+
        SetRowColumnText(row,column,tabtext);
  
::::column++;
+
        column++;
  
:::}
+
      }
  
::}
+
    }
  
:}
+
  }
 
 
  
:// all the rows have been read in
+
  // all the rows have been read in
  
:// done reading from the file, so dispose of file stuff
+
  // done reading from the file, so dispose of file stuff
  
:fclose(fp);
+
  fclose(fp);
  
:DisposeLineBuffer(line);
+
  DisposeLineBuffer(line);
 
 
:return(TRUE);
+
  return(TRUE);
  
 
}
 
}
</tt>
+
</syntaxhighlight>
  
 
==LineBuffer data structure==
 
==LineBuffer data structure==
<blockquote>
 
<tt> typedef struct {
 
  
 +
<syntaxhighlight lang=objective-c>
 +
typedef struct {
 +
 +
  unsigned long max; // maximum size of the line (i.e. size of buffer pointed to by text)
  
: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 *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 *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
  
: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
  
: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;
 
} LineBuffer;
</tt>
+
</syntaxhighlight>
</blockquote>
+
 
  
 
==Routines==
 
==Routines==
Line 147: Line 148:
 
<blockquote>
 
<blockquote>
 
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 <tt>\r</tt> or  <tt>\n</tt>. This routine DOES call <tt>rewind(fp) </tt> before returning, so <tt>fp</tt> points to the start of the file upon returning.  
 
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 <tt>\r</tt> or  <tt>\n</tt>. This routine DOES call <tt>rewind(fp) </tt> before returning, so <tt>fp</tt> points to the start of the file upon returning.  
 +
</blockquote>
 +
 +
===<tt> void SetBuffer(LineBuffer *line,char *buffer, unsigned long size); </tt>===
 +
<blockquote>
 +
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
 +
</blockquote>
 +
 +
===<tt> void RewindBuffer(LineBuffer *line,char *buffer); </tt>===
 +
<blockquote>
 +
resets the internal variable line->buffer_ptr, so we start searching for lines at the beginning of the buffer
 +
</blockquote>
 +
 +
===<tt> Boolean GetNextLineInBuffer(LineBuffer *line,char *buffer); </tt>===
 +
<blockquote>
 +
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
 +
</blockquote>
 +
 +
===<tt> unsigned long CountLinesInBuffer(LineBuffer *line,char *buffer,unsigned long size); </tt>===
 +
<blockquote>
 +
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
 
</blockquote>
 
</blockquote>

Latest revision as of 15:40, 8 July 2022

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

TabText.h
TabText.c

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