progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / base / rsvr.h
1 /* -*-c-*-
2 *
3 * Reservoir and buffer handling
4 *
5 * (c) 2017 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software: you can redistribute it and/or modify it
13 * under the terms of the GNU Library General Public License as published
14 * by the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 * USA.
26 */
27
28 #ifndef CATACOMB_RSVR_H
29 #define CATACOMB_RSVR_H
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stddef.h>
38
39 /*----- Data structures ---------------------------------------------------*/
40
41 typedef struct rsvr_policy {
42 unsigned f; /* Flags... */
43 #define RSVRF_FULL 1u /* Hold back a full reservoir */
44 unsigned blksz; /* Block size */
45 unsigned rsvrsz; /* Reservoir size; multiple of
46 * @blksz@ */
47 } rsvr_policy;
48
49 typedef struct rsvr_plan {
50 unsigned head; /* First, accumulate @head@ bytes
51 * into the reservoir */
52 unsigned from_rsvr; /* Next, process @from_rsvr@ bytes
53 * from the reservoir */
54 size_t from_input; /* Then, process @from_input@ bytes
55 * directly from the input */
56 unsigned tail; /* Finally, accumulate the remaining
57 * @tail@ bytes of input into the
58 * reservoir */
59 } rsvr_plan;
60
61 enum { RSVRSRC_RSVR, RSVRSRC_INPUT, RSVRSRC_DONE };
62
63 typedef struct rsvr_state {
64 rsvr_plan plan;
65 unsigned *used;
66 unsigned char *rsvr;
67 const unsigned char *in, *p;
68 size_t sz;
69 unsigned src;
70 } rsvr_state;
71
72 /*----- Functions provided ------------------------------------------------*/
73
74 /* --- @rsvr_mkplan@ --- *
75 *
76 * Arguments: @rsvr_plan *plan@ = pointer to plan to fill in
77 * @const rsvr_policy *pol@ = reservoir policy to follow
78 * @size_t used@ = amount of data in the reservoir
79 * @size_t insz@ = amount of fresh input data arriving
80 *
81 * Returns: ---
82 *
83 * Use: Prepares a plan for feeding input data into a block-oriented
84 * operation.
85 *
86 * The caller's code for following the plan proceeds in four
87 * parts.
88 *
89 * 1. Insert the first @plan->head@ input items into the
90 * reservoir; there will be sufficient space, and
91 * @plan->head@ will be at most @pol->blksz@.
92 *
93 * 2. Process the first @plan->from_rsvr@ items from the
94 * reservoir, shifting the remaining items forward;
95 * @plan->from_rsvr@ will be a multiple of @pol->blksz@.
96 *
97 * 3. Process the next @plan->from_input@ items directly from
98 * the input; @plan->from_input@ will be a multiple of
99 * @pol->blksz@.
100 *
101 * 4. Insert the remaining @plan->tail@ input items into the
102 * reservoir for next time.
103 */
104
105 extern void rsvr_mkplan(rsvr_plan */*plan*/, const rsvr_policy */*pol*/,
106 size_t /*used*/, size_t /*insz*/);
107
108 /* --- @rsvr_setup@ --- *
109 *
110 * Arguments: @rsvr_state *st@ = pointer to state structure to fill in
111 * @const rsvr_policy *pol@ = reservoir policy to follow
112 * @void *rsvr@ = pointer to the actual reservoir
113 * @unsigned *used@ = pointer to the reservoir level
114 * @const void *in@ = pointer to the input data
115 * @size_t insz@ = size of the input
116 *
117 * Returns: ---
118 *
119 * Use: Prepares for a simple operation. This performs the initial
120 * copy of input data into the reservoir, and prepares for the
121 * next step.
122 *
123 * After this, the calling code should usually proceed as
124 * follows.
125 *
126 * 1. Call @RSVR_NEXT@ in a sequence of loops, with
127 * successively smaller values of @n@, to process waiting
128 * data from the reservoir. Usually, each @n@ will be some
129 * multiple of the block size @pol->blksz@, and the final
130 * loop will have @n = pol->blksz@.
131 *
132 * 2. Call @rsvr_done@ to indicate that this has been done.
133 *
134 * 3. Call @RSVR_NEXT@ in a sequence of loops, as in step 1,
135 * to process the remaining data from the input buffer.
136 *
137 * 4. Call @rsvr_done@ to indicate that the job is complete.
138 */
139
140 extern void rsvr_setup(rsvr_state */*st*/, const rsvr_policy */*pol*/,
141 void */*rsvr*/, unsigned */*used*/,
142 const void */*in*/, size_t /*insz*/);
143
144 /* --- @RSVR_NEXT@, @rsvr_next@ --- *
145 *
146 * Arguments: @rsvr_state *st@ = pointer to the state structure
147 * @size_t n@ = amount of input data required, in bytes; should
148 * usually be a multiple of @pol->blksz@
149 *
150 * Returns: A pointer to the next @n@ bytes of input, or null if there is
151 * insufficient data remaining.
152 */
153
154 #define RSVR_NEXT(st, n) \
155 ((n) > (st)->sz \
156 ? 0 \
157 : ((st)->sz -= (n), \
158 (st)->p += (n), \
159 (const void *)((st)->p - (n))))
160 extern const void *rsvr_next(rsvr_state */*st*/, size_t /*n*/);
161
162 /* --- @rsvr_done@ --- *
163 *
164 * Arguments: @rsvr_state *st@ = pointer to the state structure
165 *
166 * Returns: Zero after the first pass, nonzero after the second.
167 *
168 * Use: Reports that the first or second stage (see @rsvr_setup@
169 * above) of an operation has been completed.
170 *
171 * If the first stage is complete, then this shifts stuff about
172 * in the reservoir and prepares for the second stage; if the
173 * second stage is complete, then it copies the remaining input
174 * into the reservoir and marks the state as complete.
175 */
176
177 extern int rsvr_done(rsvr_state */*st*/);
178
179 /* --- @RSVR_DO@ --- *
180 *
181 * Arguments: @st@ = pointer to state structure
182 *
183 * Use: Invoke as @RSVR_DO(st) stmt@: performs two passes of @stmt@
184 * over the reservoir and input buffers respectively.
185 */
186
187 #define RSVR_DO(st) switch (0) while (!rsvr_done(st)) case 0:
188
189 /*----- That's all, folks -------------------------------------------------*/
190
191 #ifdef __cplusplus
192 }
193 #endif
194
195 #endif