File: linebuffer.c

package info (click to toggle)
zmailer 2.99.51.52pre3-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 16,596 kB
  • ctags: 7,422
  • sloc: ansic: 90,470; sh: 3,608; makefile: 2,784; perl: 1,585; python: 115; awk: 22
file content (139 lines) | stat: -rw-r--r-- 3,542 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 *	Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *	This will be free software, but only when it is finished.
 */

/* customized routines to read in lines of potentially infinite length */

#include "hostenv.h"
#include "mailer.h"
#include <sys/file.h>
#ifndef NO_Z_IO_H
#include "../libsh/io.h"
#endif
#include "libz.h"

#ifndef	L_INCR
#define	L_INCR	1
#endif	/* L_INCR */

/*
 *  Returns the number of characters of the next line to be read. The line
 *  is pointed at by (char *)zlinebuf. This storage is part of a dynamically
 *  allocated buffer known only within this module. Code external to here
 *  should treat zlinebuf as a read-only (constant) buffer.
 */
static char	*getline_block = NULL;  /* malloc()'ed input buffer */
static char	*getline_bend;		/* end of line pointer */
static u_int	getline_blen;		/* bytes available to consume */
static u_int	getline_bsize;		/* size of malloc()'ed buffer */

char	*zlinebuf = NULL;	/* where to start consuming */

/*
 * This routine should be called between opening a file
 * and calling getline() for the first time on that file.
 */

void
initzline(blksize)
	long blksize;
{
	if (getline_block == NULL) {
		getline_bsize = blksize;
		if (getline_bsize < BUFSIZ)
			getline_bsize = BUFSIZ;
		getline_block = (char *)emalloc(getline_bsize);
	}
	getline_blen = 0;
}

void
repos_zgetline(fp,newpos)
	FILE *fp;
	off_t newpos;
{
	getline_blen = 0;
	fseek(fp, newpos, 0);
}

/*
 * Return the number of bytes starting from zlinebuf, which make up a line.
 */

int
zgetline(fp)
	FILE *fp;
{
	register char	*cp;
	register u_int	n;

	/* assert getline_block != NULL */
	if (getline_blen == 0 ||
	    getline_bend >= (getline_block + getline_bsize)) {
	  getline_blen = fread(getline_block, 1, getline_bsize-1, fp);
	  if (getline_blen == 0) /* Error or EOF, never mind which */
	    return 0;
	  getline_bend = getline_block;
	}
	while (1) {
	  /* look for end of line in what remains of the input buffer */
	  for (cp = getline_bend, n = 0; n < getline_blen; ++n, ++cp)
	    if (*cp == '\n') {
	      zlinebuf = getline_bend;
	      getline_bend = ++cp;
	      getline_blen -= ++n;
	      return n;
	    }
	  /* copy the partial line to the beginning of the input buffer */
	  if (getline_bend > getline_block)
	    memcpy(getline_block, getline_bend, getline_blen);
	  /* get some more bytes which will hopefully contain a newline */
	  n = getline_bsize - getline_blen;
	  if (n <= 0) {		/* grow the buffer */
	    n = getline_bsize;
	    getline_bsize *= 2;
	    getline_block = (char *)erealloc(getline_block,
					     getline_bsize);
	  }
	  n = fread(getline_block + getline_blen, 1, n-1, fp);
	  if (n == 0) {
	    /* the file doesn't terminate in a newline */
	    n = getline_blen;
	    getline_blen = 0;
	    zlinebuf = getline_block;
	    return n;
	  }
	  getline_blen += n;
	  getline_bend = getline_block;
	}
	/* NOTREACHED */
}

/*
 * Return the number of bytes starting from zlinebuf, left in zlinebuf.
 * This is used to get the remaining bytes that have been read from the
 * file descriptor (and perhaps cannot be reread when the fp refers to
 * a pipe), to enable efficient copying of the rest of the data.
 */

int
zlinegetrest()
{
	/* assert getline_block != NULL */
	if (getline_blen <= 0 || getline_bend >= getline_block + getline_bsize)
		return 0;
	zlinebuf = getline_bend;
	return getline_blen;
}

/*
 *  Determine the position of zlinebuf in the open file described by fp.
 */

long
zlineoffset(fp)
	FILE *fp;
{
	return ftell(fp) - getline_blen;
}