1 /* Saving history in a line-based input stream. 2 * 3 * SRE, Mon Dec 28 09:51:51 2009 [Zaragoza] 4 */ 5 #ifndef eslRECORDER_INCLUDED 6 #define eslRECORDER_INCLUDED 7 #include "esl_config.h" 8 9 #include <stdio.h> 10 #ifdef HAVE_SYS_TYPES_H 11 #include <sys/types.h> 12 #endif 13 14 15 /* Object: ESL_RECORDER 16 * 17 * A history of a line-based input stream. 18 * Allows (limited) rewinding in nonrewindable input streams; 19 * also allows block-based parsing (as opposed to line-based). 20 * 21 * The history is kept in a rolling array of string ptrs. The 22 * bookkeeping involved in indexing this array can be confusing. 23 * 24 * Lines in the file are numbered 0..N-1. 25 * (N isn't known; we'll be reading sequentially.) 26 * Lines in the recorder are 0..nalloc-1. 27 * 28 * The recorder keeps track of how many lines it has read so far, in 29 * <nread>. 30 * 31 * The recorder can be backed up to any previous line. It sets <ncurr> 32 * to be the number of lines it *appears* to have read so far; 33 * that is, the next line it will return to the caller, upon a call 34 * to esl_recorder_Read(), is line <ncurr>. 35 * 36 * A window of MIN(nread, nalloc) lines is stored; 37 * consisting of line numbers MAX(baseline, nread-nalloc) .. nread-1). 38 * 39 * A line n in the file (0..n..N-1) corresponds to 40 * an index i in the recorder by these transforms: 41 * i = (n-baseline) % nalloc 42 * n = i + MAX(baseline, nread-nalloc) 43 * 44 * Normally the baseline for the modulo calculation is just 0. 45 * 46 * The line array is circularly permuted (out of order) when 47 * (nread-baseline) / nalloc != 0. 48 */ 49 typedef struct { 50 FILE *fp; /* stream that we're reading line by line */ 51 52 char **line; /* lines from input, line[0..nalloc-1] */ 53 int nalloc; /* max number of lines remembered */ 54 int *lalloc; /* alloc for each line[0..nalloc-1][0..lalloc[i]-1] */ 55 off_t *offset; /* disk offsets to starts of each line */ 56 57 int nread; /* max # of lines read from file in any pass [1..] */ 58 int ncurr; /* # of lines into file in current pass [1..] */ 59 60 int baseline; /* line origin for n<->i transform [0..] */ 61 int markline; /* line origin for start of current block [-1;0..] */ 62 } ESL_RECORDER; 63 64 65 extern ESL_RECORDER *esl_recorder_Create (FILE *fp, int maxlines); 66 extern int esl_recorder_ResizeTo (ESL_RECORDER *rc, int new_maxlines); 67 extern int esl_recorder_GetFirst (ESL_RECORDER *rc); 68 extern int esl_recorder_GetLast (ESL_RECORDER *rc); 69 extern int esl_recorder_GetCurrent(ESL_RECORDER *rc); 70 extern int esl_recorder_GetNext (ESL_RECORDER *rc); 71 extern void esl_recorder_Destroy (ESL_RECORDER *rc); 72 73 extern int esl_recorder_Read(ESL_RECORDER *rc, char **opt_line); 74 extern int esl_recorder_Position(ESL_RECORDER *rc, int linenumber); 75 extern int esl_recorder_MarkBlock(ESL_RECORDER *rc, int markline); 76 extern int esl_recorder_UnmarkBlock(ESL_RECORDER *rc); 77 extern int esl_recorder_GetBlock(ESL_RECORDER *rc, char ***opt_lines, int **opt_lalloc, off_t **opt_offset, int *opt_nlines); 78 79 #endif /*eslRECORDER_INCLUDED*/ 80 81 82