Willy Tarreau | c7e4238 | 2012-08-24 19:22:53 +0200 | [diff] [blame^] | 1 | /* |
| 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 | */ |
| 25 | void 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 | */ |
| 56 | void 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 | */ |
| 115 | void 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 | */ |