xref: /memcached-1.4.29/bipbuffer.c (revision 1ecdbdb0)
1*916fff36Sdormando /**
2*916fff36Sdormando  * Copyright (c) 2011, Willem-Hendrik Thiart
3*916fff36Sdormando  * Use of this source code is governed by a BSD-style license that can be
4*916fff36Sdormando  * found in the LICENSE.bipbuffer file.
5*916fff36Sdormando  *
6*916fff36Sdormando  * @file
7*916fff36Sdormando  * @author  Willem Thiart [email protected]
8*916fff36Sdormando  */
9*916fff36Sdormando 
10*916fff36Sdormando #include "stdio.h"
11*916fff36Sdormando #include <stdlib.h>
12*916fff36Sdormando 
13*916fff36Sdormando /* for memcpy */
14*916fff36Sdormando #include <string.h>
15*916fff36Sdormando 
16*916fff36Sdormando #include "bipbuffer.h"
17*916fff36Sdormando 
bipbuf_sizeof(const unsigned int size)18*916fff36Sdormando static size_t bipbuf_sizeof(const unsigned int size)
19*916fff36Sdormando {
20*916fff36Sdormando     return sizeof(bipbuf_t) + size;
21*916fff36Sdormando }
22*916fff36Sdormando 
bipbuf_unused(const bipbuf_t * me)23*916fff36Sdormando int bipbuf_unused(const bipbuf_t* me)
24*916fff36Sdormando {
25*916fff36Sdormando     if (1 == me->b_inuse)
26*916fff36Sdormando         /* distance between region B and region A */
27*916fff36Sdormando         return me->a_start - me->b_end;
28*916fff36Sdormando     else
29*916fff36Sdormando         return me->size - me->a_end;
30*916fff36Sdormando }
31*916fff36Sdormando 
bipbuf_size(const bipbuf_t * me)32*916fff36Sdormando int bipbuf_size(const bipbuf_t* me)
33*916fff36Sdormando {
34*916fff36Sdormando     return me->size;
35*916fff36Sdormando }
36*916fff36Sdormando 
bipbuf_used(const bipbuf_t * me)37*916fff36Sdormando int bipbuf_used(const bipbuf_t* me)
38*916fff36Sdormando {
39*916fff36Sdormando     return (me->a_end - me->a_start) + me->b_end;
40*916fff36Sdormando }
41*916fff36Sdormando 
bipbuf_init(bipbuf_t * me,const unsigned int size)42*916fff36Sdormando void bipbuf_init(bipbuf_t* me, const unsigned int size)
43*916fff36Sdormando {
44*916fff36Sdormando     me->a_start = me->a_end = me->b_end = 0;
45*916fff36Sdormando     me->size = size;
46*916fff36Sdormando     me->b_inuse = 0;
47*916fff36Sdormando }
48*916fff36Sdormando 
bipbuf_new(const unsigned int size)49*916fff36Sdormando bipbuf_t *bipbuf_new(const unsigned int size)
50*916fff36Sdormando {
51*916fff36Sdormando     bipbuf_t *me = malloc(bipbuf_sizeof(size));
52*916fff36Sdormando     if (!me)
53*916fff36Sdormando         return NULL;
54*916fff36Sdormando     bipbuf_init(me, size);
55*916fff36Sdormando     return me;
56*916fff36Sdormando }
57*916fff36Sdormando 
bipbuf_free(bipbuf_t * me)58*916fff36Sdormando void bipbuf_free(bipbuf_t* me)
59*916fff36Sdormando {
60*916fff36Sdormando     free(me);
61*916fff36Sdormando }
62*916fff36Sdormando 
bipbuf_is_empty(const bipbuf_t * me)63*916fff36Sdormando int bipbuf_is_empty(const bipbuf_t* me)
64*916fff36Sdormando {
65*916fff36Sdormando     return me->a_start == me->a_end;
66*916fff36Sdormando }
67*916fff36Sdormando 
68*916fff36Sdormando /* find out if we should turn on region B
69*916fff36Sdormando  * ie. is the distance from A to buffer's end less than B to A? */
__check_for_switch_to_b(bipbuf_t * me)70*916fff36Sdormando static void __check_for_switch_to_b(bipbuf_t* me)
71*916fff36Sdormando {
72*916fff36Sdormando     if (me->size - me->a_end < me->a_start - me->b_end)
73*916fff36Sdormando         me->b_inuse = 1;
74*916fff36Sdormando }
75*916fff36Sdormando 
76*916fff36Sdormando /* TODO: DOCUMENT THESE TWO FUNCTIONS */
bipbuf_request(bipbuf_t * me,const int size)77*916fff36Sdormando unsigned char *bipbuf_request(bipbuf_t* me, const int size)
78*916fff36Sdormando {
79*916fff36Sdormando     if (bipbuf_unused(me) < size)
80*916fff36Sdormando         return 0;
81*916fff36Sdormando     if (1 == me->b_inuse)
82*916fff36Sdormando     {
83*916fff36Sdormando         return (unsigned char *)me->data + me->b_end;
84*916fff36Sdormando     }
85*916fff36Sdormando     else
86*916fff36Sdormando     {
87*916fff36Sdormando         return (unsigned char *)me->data + me->a_end;
88*916fff36Sdormando     }
89*916fff36Sdormando }
90*916fff36Sdormando 
bipbuf_push(bipbuf_t * me,const int size)91*916fff36Sdormando int bipbuf_push(bipbuf_t* me, const int size)
92*916fff36Sdormando {
93*916fff36Sdormando     if (bipbuf_unused(me) < size)
94*916fff36Sdormando         return 0;
95*916fff36Sdormando 
96*916fff36Sdormando     if (1 == me->b_inuse)
97*916fff36Sdormando     {
98*916fff36Sdormando         me->b_end += size;
99*916fff36Sdormando     }
100*916fff36Sdormando     else
101*916fff36Sdormando     {
102*916fff36Sdormando         me->a_end += size;
103*916fff36Sdormando     }
104*916fff36Sdormando 
105*916fff36Sdormando     __check_for_switch_to_b(me);
106*916fff36Sdormando     return size;
107*916fff36Sdormando }
108*916fff36Sdormando 
bipbuf_offer(bipbuf_t * me,const unsigned char * data,const int size)109*916fff36Sdormando int bipbuf_offer(bipbuf_t* me, const unsigned char *data, const int size)
110*916fff36Sdormando {
111*916fff36Sdormando     /* not enough space */
112*916fff36Sdormando     if (bipbuf_unused(me) < size)
113*916fff36Sdormando         return 0;
114*916fff36Sdormando 
115*916fff36Sdormando     if (1 == me->b_inuse)
116*916fff36Sdormando     {
117*916fff36Sdormando         memcpy(me->data + me->b_end, data, size);
118*916fff36Sdormando         me->b_end += size;
119*916fff36Sdormando     }
120*916fff36Sdormando     else
121*916fff36Sdormando     {
122*916fff36Sdormando         memcpy(me->data + me->a_end, data, size);
123*916fff36Sdormando         me->a_end += size;
124*916fff36Sdormando     }
125*916fff36Sdormando 
126*916fff36Sdormando     __check_for_switch_to_b(me);
127*916fff36Sdormando     return size;
128*916fff36Sdormando }
129*916fff36Sdormando 
bipbuf_peek(const bipbuf_t * me,const unsigned int size)130*916fff36Sdormando unsigned char *bipbuf_peek(const bipbuf_t* me, const unsigned int size)
131*916fff36Sdormando {
132*916fff36Sdormando     /* make sure we can actually peek at this data */
133*916fff36Sdormando     if (me->size < me->a_start + size)
134*916fff36Sdormando         return NULL;
135*916fff36Sdormando 
136*916fff36Sdormando     if (bipbuf_is_empty(me))
137*916fff36Sdormando         return NULL;
138*916fff36Sdormando 
139*916fff36Sdormando     return (unsigned char *)me->data + me->a_start;
140*916fff36Sdormando }
141*916fff36Sdormando 
bipbuf_peek_all(const bipbuf_t * me,unsigned int * size)142*916fff36Sdormando unsigned char *bipbuf_peek_all(const bipbuf_t* me, unsigned int *size)
143*916fff36Sdormando {
144*916fff36Sdormando     if (bipbuf_is_empty(me))
145*916fff36Sdormando         return NULL;
146*916fff36Sdormando 
147*916fff36Sdormando     *size = me->a_end - me->a_start;
148*916fff36Sdormando     return (unsigned char*)me->data + me->a_start;
149*916fff36Sdormando }
150*916fff36Sdormando 
bipbuf_poll(bipbuf_t * me,const unsigned int size)151*916fff36Sdormando unsigned char *bipbuf_poll(bipbuf_t* me, const unsigned int size)
152*916fff36Sdormando {
153*916fff36Sdormando     if (bipbuf_is_empty(me))
154*916fff36Sdormando         return NULL;
155*916fff36Sdormando 
156*916fff36Sdormando     /* make sure we can actually poll this data */
157*916fff36Sdormando     if (me->size < me->a_start + size)
158*916fff36Sdormando         return NULL;
159*916fff36Sdormando 
160*916fff36Sdormando     void *end = me->data + me->a_start;
161*916fff36Sdormando     me->a_start += size;
162*916fff36Sdormando 
163*916fff36Sdormando     /* we seem to be empty.. */
164*916fff36Sdormando     if (me->a_start == me->a_end)
165*916fff36Sdormando     {
166*916fff36Sdormando         /* replace a with region b */
167*916fff36Sdormando         if (1 == me->b_inuse)
168*916fff36Sdormando         {
169*916fff36Sdormando             me->a_start = 0;
170*916fff36Sdormando             me->a_end = me->b_end;
171*916fff36Sdormando             me->b_end = me->b_inuse = 0;
172*916fff36Sdormando         }
173*916fff36Sdormando         else
174*916fff36Sdormando             /* safely move cursor back to the start because we are empty */
175*916fff36Sdormando             me->a_start = me->a_end = 0;
176*916fff36Sdormando     }
177*916fff36Sdormando 
178*916fff36Sdormando     __check_for_switch_to_b(me);
179*916fff36Sdormando     return end;
180*916fff36Sdormando }
181