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