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