blob: 764f692846c1ddb952d1e330df86909a6888ad3c [file] [log] [blame]
Willy Tarreauc7e42382012-08-24 19:22:53 +02001/*
2 * Buffer management functions.
3 *
4 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <string.h>
15
16#include <common/config.h>
17#include <common/buffer.h>
18
19#include <types/global.h>
20
21/* This function realigns input data in a possibly wrapping buffer so that it
22 * becomes contiguous and starts at the beginning of the buffer area. The
23 * function may only be used when the buffer's output is empty.
24 */
25void buffer_slow_realign(struct buffer *buf)
26{
27 /* two possible cases :
28 * - the buffer is in one contiguous block, we move it in-place
29 * - the buffer is in two blocks, we move it via the swap_buffer
30 */
31 if (buf->i) {
32 int block1 = buf->i;
33 int block2 = 0;
34 if (buf->p + buf->i > buf->data + buf->size) {
35 /* non-contiguous block */
36 block1 = buf->data + buf->size - buf->p;
37 block2 = buf->p + buf->i - (buf->data + buf->size);
38 }
39 if (block2)
40 memcpy(swap_buffer, buf->data, block2);
41 memmove(buf->data, buf->p, block1);
42 if (block2)
43 memcpy(buf->data + block1, swap_buffer, block2);
44 }
45
46 buf->p = buf->data;
47}
48
49
50/* Realigns a possibly non-contiguous buffer by bouncing bytes from source to
51 * destination. It does not use any intermediate buffer and does the move in
52 * place, though it will be slower than a simple memmove() on contiguous data,
53 * so it's desirable to use it only on non-contiguous buffers. No pointers are
54 * changed, the caller is responsible for that.
55 */
56void buffer_bounce_realign(struct buffer *buf)
57{
58 int advance, to_move;
59 char *from, *to;
60
61 from = bo_ptr(buf);
62 advance = buf->data + buf->size - from;
63 if (!advance)
64 return;
65
66 to_move = buffer_len(buf);
67 while (to_move) {
68 char last, save;
69
70 last = *from;
71 to = from + advance;
72 if (to >= buf->data + buf->size)
73 to -= buf->size;
74
75 while (1) {
76 save = *to;
77 *to = last;
78 last = save;
79 to_move--;
80 if (!to_move)
81 break;
82
83 /* check if we went back home after rotating a number of bytes */
84 if (to == from)
85 break;
86
87 /* if we ended up in the empty area, let's walk to next place. The
88 * empty area is either between buf->r and from or before from or
89 * after buf->r.
90 */
91 if (from > bi_end(buf)) {
92 if (to >= bi_end(buf) && to < from)
93 break;
94 } else if (from < bi_end(buf)) {
95 if (to < from || to >= bi_end(buf))
96 break;
97 }
98
99 /* we have overwritten a byte of the original set, let's move it */
100 to += advance;
101 if (to >= buf->data + buf->size)
102 to -= buf->size;
103 }
104
105 from++;
106 if (from >= buf->data + buf->size)
107 from -= buf->size;
108 }
109}
110
111
112/*
113 * Dumps part or all of a buffer.
114 */
115void buffer_dump(FILE *o, struct buffer *b, int from, int to)
116{
117 fprintf(o, "Dumping buffer %p\n", b);
118 fprintf(o, " data=%p o=%d i=%d p=%p\n",
119 b->data, b->o, b->i, b->p);
120
121 if (!to || to > buffer_len(b))
122 to = buffer_len(b);
123
124 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
125 for (; from < to; from++) {
126 if ((from & 15) == 0)
127 fprintf(o, " %04x: ", from);
128 fprintf(o, "%02x ", b->data[from]);
129 if ((from & 15) == 7)
130 fprintf(o, "- ");
131 else if (((from & 15) == 15) && (from != to-1))
132 fprintf(o, "\n");
133 }
134 fprintf(o, "\n--\n");
135}
136
137
138/*
139 * Local variables:
140 * c-indent-level: 8
141 * c-basic-offset: 8
142 * End:
143 */