source: mainline/uspace/lib/http/src/receive-buffer.c@ 47b2d7e3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 47b2d7e3 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[ff364f1]1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * Copyright (c) 2013 Martin Sucha
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup http
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdlib.h>
38#include <str.h>
39#include <errno.h>
40#include <macros.h>
[3ce68b7]41#include <adt/list.h>
[ff364f1]42
[b623b68]43#include <http/receive-buffer.h>
[ff364f1]44
[b7fd2a0]45errno_t recv_buffer_init(receive_buffer_t *rb, size_t buffer_size,
[ff364f1]46 receive_func_t receive, void *client_data)
47{
48 rb->receive = receive;
49 rb->client_data = client_data;
[a35b458]50
[ff364f1]51 rb->in = 0;
52 rb->out = 0;
53 rb->size = buffer_size;
[a35b458]54
[3ce68b7]55 list_initialize(&rb->marks);
[a35b458]56
[ff364f1]57 rb->buffer = malloc(buffer_size);
58 if (rb->buffer == NULL)
59 return ENOMEM;
60 return EOK;
61}
62
[b7fd2a0]63static errno_t dummy_receive(void *unused, void *buf, size_t buf_size,
[9a09212]64 size_t *nrecv)
[3ce68b7]65{
[9a09212]66 *nrecv = 0;
67 return EOK;
[3ce68b7]68}
69
[b7fd2a0]70errno_t recv_buffer_init_const(receive_buffer_t *rb, void *buf, size_t size)
[3ce68b7]71{
[b7fd2a0]72 errno_t rc = recv_buffer_init(rb, size, dummy_receive, NULL);
[3ce68b7]73 if (rc != EOK)
74 return rc;
[a35b458]75
[3ce68b7]76 memcpy(rb->buffer, buf, size);
77 rb->in = size;
78 return EOK;
79}
80
[ff364f1]81void recv_buffer_fini(receive_buffer_t *rb)
82{
83 free(rb->buffer);
84}
85
86void recv_reset(receive_buffer_t *rb)
87{
88 rb->in = 0;
89 rb->out = 0;
90}
91
[3ce68b7]92void recv_mark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
93{
94 link_initialize(&mark->link);
95 list_append(&mark->link, &rb->marks);
96 recv_mark_update(rb, mark);
97}
98
99void recv_unmark(receive_buffer_t *rb, receive_buffer_mark_t *mark)
100{
101 list_remove(&mark->link);
102}
103
104void recv_mark_update(receive_buffer_t *rb, receive_buffer_mark_t *mark)
105{
106 mark->offset = rb->out;
107}
108
[b7fd2a0]109errno_t recv_cut(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, void **out_buf, size_t *out_size)
[3ce68b7]110{
111 if (a->offset > b->offset)
112 return EINVAL;
[a35b458]113
[3ce68b7]114 size_t size = b->offset - a->offset;
115 void *buf = malloc(size);
116 if (buf == NULL)
117 return ENOMEM;
[a35b458]118
[3ce68b7]119 memcpy(buf, rb->buffer + a->offset, size);
120 *out_buf = buf;
121 *out_size = size;
122 return EOK;
123}
124
[b7fd2a0]125errno_t recv_cut_str(receive_buffer_t *rb, receive_buffer_mark_t *a, receive_buffer_mark_t *b, char **out_buf)
[3ce68b7]126{
127 if (a->offset > b->offset)
128 return EINVAL;
[a35b458]129
[3ce68b7]130 size_t size = b->offset - a->offset;
131 char *buf = malloc(size + 1);
132 if (buf == NULL)
133 return ENOMEM;
[a35b458]134
[3ce68b7]135 memcpy(buf, rb->buffer + a->offset, size);
136 buf[size] = 0;
137 for (size_t i = 0; i < size; i++) {
138 if (buf[i] == 0) {
139 free(buf);
140 return EIO;
141 }
142 }
143 *out_buf = buf;
144 return EOK;
145}
146
147
[ff364f1]148/** Receive one character (with buffering) */
[b7fd2a0]149errno_t recv_char(receive_buffer_t *rb, char *c, bool consume)
[ff364f1]150{
151 if (rb->out == rb->in) {
[3ce68b7]152 size_t free = rb->size - rb->in;
153 if (free == 0) {
154 size_t min_mark = rb->size;
155 list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
156 min_mark = min(min_mark, mark->offset);
157 }
[a35b458]158
[3ce68b7]159 if (min_mark == 0)
160 return ELIMIT;
[a35b458]161
[3ce68b7]162 size_t new_in = rb->in - min_mark;
163 memmove(rb->buffer, rb->buffer + min_mark, new_in);
164 rb->out = rb->in = new_in;
165 free = rb->size - rb->in;
166 list_foreach(rb->marks, link, receive_buffer_mark_t, mark) {
167 mark->offset -= min_mark;
168 }
169 }
[a35b458]170
[9a09212]171 size_t nrecv;
[b7fd2a0]172 errno_t rc = rb->receive(rb->client_data, rb->buffer + rb->in, free, &nrecv);
[9a09212]173 if (rc != EOK)
[ff364f1]174 return rc;
[a35b458]175
[9a09212]176 rb->in = nrecv;
[ff364f1]177 }
[a35b458]178
[ff364f1]179 *c = rb->buffer[rb->out];
180 if (consume)
181 rb->out++;
182 return EOK;
183}
184
[b7fd2a0]185errno_t recv_buffer(receive_buffer_t *rb, char *buf, size_t buf_size,
[9a09212]186 size_t *nrecv)
[ff364f1]187{
[9a09212]188 /* Flush any buffered data */
[ff364f1]189 if (rb->out != rb->in) {
190 size_t size = min(rb->in - rb->out, buf_size);
191 memcpy(buf, rb->buffer + rb->out, size);
192 rb->out += size;
[9a09212]193 *nrecv = size;
194 return EOK;
[ff364f1]195 }
[a35b458]196
[9a09212]197 return rb->receive(rb->client_data, buf, buf_size, nrecv);
[ff364f1]198}
199
[3ce68b7]200/** Receive a character and if it is c, discard it from input buffer
[9a09212]201 * @param ndisc Place to store number of characters discarded
[cde999a]202 * @return EOK or an error code
[3ce68b7]203 */
[b7fd2a0]204errno_t recv_discard(receive_buffer_t *rb, char discard, size_t *ndisc)
[ff364f1]205{
206 char c = 0;
[b7fd2a0]207 errno_t rc = recv_char(rb, &c, false);
[ff364f1]208 if (rc != EOK)
209 return rc;
[9a09212]210 if (c != discard) {
211 *ndisc = 0;
212 return EOK;
213 }
[3ce68b7]214 rc = recv_char(rb, &c, true);
215 if (rc != EOK)
216 return rc;
[9a09212]217 *ndisc = 1;
218 return EOK;
[3ce68b7]219}
220
[408424e]221/** Receive a prefix of constant string discard and return number of bytes read
[9a09212]222 * @param ndisc Place to store number of characters discarded
[cde999a]223 * @return EOK or an error code
[408424e]224 */
[b7fd2a0]225errno_t recv_discard_str(receive_buffer_t *rb, const char *discard, size_t *ndisc)
[408424e]226{
227 size_t discarded = 0;
228 while (*discard) {
[9a09212]229 size_t nd;
[b7fd2a0]230 errno_t rc = recv_discard(rb, *discard, &nd);
[9a09212]231 if (rc != EOK)
[408424e]232 return rc;
[9a09212]233 if (nd == 0)
[408424e]234 break;
[9a09212]235 discarded += nd;
[408424e]236 discard++;
237 }
[9a09212]238
239 *ndisc = discarded;
240 return EOK;
[408424e]241}
242
[b7fd2a0]243errno_t recv_while(receive_buffer_t *rb, char_class_func_t class)
[408424e]244{
245 while (true) {
246 char c = 0;
[b7fd2a0]247 errno_t rc = recv_char(rb, &c, false);
[408424e]248 if (rc != EOK)
249 return rc;
[a35b458]250
[408424e]251 if (!class(c))
252 break;
[a35b458]253
[408424e]254 rc = recv_char(rb, &c, true);
255 if (rc != EOK)
256 return rc;
257 }
[a35b458]258
[9a09212]259 return EOK;
[408424e]260}
261
[3ce68b7]262/** Receive an end of line, either CR, LF, CRLF or LFCR
263 *
[9a09212]264 * @param nrecv Place to store number of bytes received (zero if
265 * no newline is present in the stream)
[cde999a]266 * @return EOK on success or an error code
[3ce68b7]267 */
[b7fd2a0]268errno_t recv_eol(receive_buffer_t *rb, size_t *nrecv)
[3ce68b7]269{
270 char c = 0;
[b7fd2a0]271 errno_t rc = recv_char(rb, &c, false);
[3ce68b7]272 if (rc != EOK)
273 return rc;
[a35b458]274
[9a09212]275 if (c != '\r' && c != '\n') {
276 *nrecv = 0;
277 return EOK;
278 }
[a35b458]279
[3ce68b7]280 rc = recv_char(rb, &c, true);
281 if (rc != EOK)
282 return rc;
[a35b458]283
[9a09212]284 size_t nr;
285 rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'), &nr);
286 if (rc != EOK)
287 return rc;
[a35b458]288
[9a09212]289 *nrecv = 1 + nr;
290 return EOK;
[ff364f1]291}
292
293/* Receive a single line */
[b7fd2a0]294errno_t recv_line(receive_buffer_t *rb, char *line, size_t size, size_t *nrecv)
[ff364f1]295{
296 size_t written = 0;
[9a09212]297 size_t nr;
[a35b458]298
[ff364f1]299 while (written < size) {
300 char c = 0;
[b7fd2a0]301 errno_t rc = recv_char(rb, &c, true);
[ff364f1]302 if (rc != EOK)
303 return rc;
304 if (c == '\n') {
[9a09212]305 rc = recv_discard(rb, '\r', &nr);
306 if (rc != EOK)
307 return rc;
308
[ff364f1]309 line[written++] = 0;
[9a09212]310 *nrecv = written;
311 return EOK;
[ff364f1]312 }
313 else if (c == '\r') {
[9a09212]314 rc = recv_discard(rb, '\n', &nr);
315 if (rc != EOK)
316 return rc;
[ff364f1]317 line[written++] = 0;
[9a09212]318 *nrecv = written;
319 return EOK;
[ff364f1]320 }
321 line[written++] = c;
322 }
[a35b458]323
[ff364f1]324 return ELIMIT;
325}
326
327/** @}
328 */
Note: See TracBrowser for help on using the repository browser.