summaryrefslogtreecommitdiff
path: root/fitz/filt_pipeline.c
blob: c6b28ebd238c826b27aa9f04645722346cb2791b (plain)
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
#include "fitz_base.h"
#include "fitz_stream.h"

#define noDEBUG 1

typedef struct fz_pipeline_s fz_pipeline;

fz_error * fz_processpipeline(fz_filter *filter, fz_buffer *in, fz_buffer *out);

struct fz_pipeline_s
{
	fz_filter super;
	fz_filter *head;
	fz_buffer *buffer;
	fz_filter *tail;
	int tailneedsin;
};

fz_error *
fz_chainpipeline(fz_filter **fp, fz_filter *head, fz_filter *tail, fz_buffer *buf)
{
	FZ_NEWFILTER(fz_pipeline, p, pipeline);
	p->head = fz_keepfilter(head);
	p->tail = fz_keepfilter(tail);
	p->tailneedsin = 1;
	p->buffer = fz_keepbuffer(buf);
	return fz_okay;
}

void
fz_unchainpipeline(fz_filter *filter, fz_filter **oldfp, fz_buffer **oldbp)
{
	fz_pipeline *p = (fz_pipeline*)filter;

	*oldfp = fz_keepfilter(p->head);
	*oldbp = fz_keepbuffer(p->buffer);

	fz_dropfilter(filter);
}

fz_error *
fz_newpipeline(fz_filter **fp, fz_filter *head, fz_filter *tail)
{
	fz_error *error;

	FZ_NEWFILTER(fz_pipeline, p, pipeline);
	p->head = fz_keepfilter(head);
	p->tail = fz_keepfilter(tail);
	p->tailneedsin = 1;

	error = fz_newbuffer(&p->buffer, FZ_BUFSIZE);
	if (error)
	{
	    fz_free(p);
	    return fz_rethrow(error, "cannot create buffer");
	}

	return fz_okay;
}

void
fz_droppipeline(fz_filter *filter)
{
	fz_pipeline *p = (fz_pipeline*)filter;
	fz_dropfilter(p->head);
	fz_dropfilter(p->tail);
	fz_dropbuffer(p->buffer);
}

fz_error *
fz_processpipeline(fz_filter *filter, fz_buffer *in, fz_buffer *out)
{
	fz_pipeline *p = (fz_pipeline*)filter;
	fz_error *e;

	if (p->buffer->eof)
		goto tail;

	if (p->tailneedsin && p->head->produced)
		goto tail;

head:
	e = fz_process(p->head, in, p->buffer);

	if (e == fz_ioneedin)
		return fz_ioneedin;

	else if (e == fz_ioneedout)
	{
		if (p->tailneedsin && !p->head->produced)
		{
			fz_error *be = nil;
			if (p->buffer->rp > p->buffer->bp)
				be = fz_rewindbuffer(p->buffer);
			else
				be = fz_growbuffer(p->buffer);
			if (be)
				return be;
			goto head;
		}
		goto tail;
	}

	else if (e == fz_iodone)
		goto tail;

	else if (e)
		return fz_rethrow(e, "cannot process head filter");

	else
		return fz_okay;

tail:
	e = fz_process(p->tail, p->buffer, out);

	if (e == fz_ioneedin)
	{
		if (p->buffer->eof)
			return fz_throw("ioerror: premature eof in pipeline");
		p->tailneedsin = 1;
		goto head;
	}

	else if (e == fz_ioneedout)
	{
		p->tailneedsin = 0;
		return fz_ioneedout;
	}

	else if (e == fz_iodone)
		return fz_iodone;

	else if (e)
		return fz_rethrow(e, "cannot process tail filter");

	else
		return fz_okay;
}