• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "cbuffer.h"
13 #include "android/utils/stralloc.h"
14 #include <string.h>
15 #include <stdlib.h>
16 #include <assert.h>
17 #include <stdio.h>
18 
19 #define  DEBUG  0
20 
21 #if DEBUG
22 #  define  ASSERT(cond,fmt,...)  ({ if (!(cond)) { fprintf(stderr, fmt, __VA_ARGS__); assert(cond); } })
23 #else
24 #  define  ASSERT(cond,fmt,...)  ((void)0)
25 #endif
26 
27 #if DEBUG
28 void
cbuffer_assert(CBuffer * cb,const char * file,long lineno)29 cbuffer_assert( CBuffer*  cb, const char*  file, long  lineno )
30 {
31     const char*  reason = NULL;
32 
33     if (cb->rpos < 0 || cb->rpos >= cb->size) {
34         reason = "rpos is out of bounds";
35     }
36     else if (cb->count < 0 || cb->count > cb->size) {
37         reason = "count is incorrect";
38     }
39     if (!reason)
40         return;
41 
42     fprintf(stderr, "assert:%s:%ld: assertion failed: %s (pos=%d count=%d size=%d)\n",
43             file, lineno, reason, cb->rpos, cb->count, cb->size);
44     assert(0);
45 }
46 #  define  CBUFFER_ASSERT(cb)  cbuffer_assert(cb,__FUNCTION__,__LINE__)
47 #else
48 #  define  CBUFFER_ASSERT(cb)  ((void)0)
49 #endif
50 
51 int
cbuffer_write_peek(CBuffer * cb,uint8_t ** pbase)52 cbuffer_write_peek( CBuffer*  cb, uint8_t*  *pbase )
53 {
54     int  wpos  = cb->rpos + cb->count;
55     int  avail = cb->size - cb->count;
56 
57     CBUFFER_ASSERT(cb);
58 
59     if (wpos >= cb->size)
60         wpos -= cb->size;
61 
62     if (wpos + avail > cb->size)
63         avail = cb->size - wpos;
64 
65     *pbase = cb->buff + wpos;
66     return avail;
67 }
68 
69 void
cbuffer_write_step(CBuffer * cb,int len)70 cbuffer_write_step( CBuffer*  cb, int  len )
71 {
72     CBUFFER_ASSERT(cb);
73 
74     cb->count += len;
75     if (cb->count > cb->size)
76         cb->count = cb->size;
77 }
78 
79 
80 int
cbuffer_write(CBuffer * cb,const void * from,int len)81 cbuffer_write( CBuffer*  cb, const void*  from, int  len )
82 {
83     int  len2 = len;
84 
85     CBUFFER_ASSERT(cb);
86 
87     while (len2 > 0) {
88         int  avail = cb->size - cb->count;
89         int  wpos  = cb->rpos + cb->count;
90 
91         ASSERT(avail >= 0, "avail is negative: %d", avail);
92 
93         if (avail == 0)
94             break;
95 
96         if (wpos >= cb->size)
97             wpos -= cb->size;
98 
99         ASSERT( wpos >= 0 && wpos < cb->size, "wpos is out-of-bounds: %d (rpos=%d)", wpos, cb->rpos);
100 
101         if (wpos + avail > cb->size)
102             avail = cb->size - wpos;
103 
104         if (avail > len2)
105             avail = len2;
106 
107         memcpy( cb->buff + wpos, (const char*)from, avail );
108 
109         from  = (char*)from + avail;
110         len2 -= avail;
111         cb->count += avail;
112     }
113     return len - len2;
114 }
115 
116 int
cbuffer_read(CBuffer * cb,void * to,int len)117 cbuffer_read( CBuffer*  cb, void*  to, int  len )
118 {
119     int   len2 = len;
120 
121     CBUFFER_ASSERT(cb);
122 
123     while (len2 > 0) {
124         int  avail = cb->count;
125         int  rpos = cb->rpos;
126 
127         ASSERT(avail >= 0, "avail is negative: %d", avail);
128 
129         if (avail == 0)
130             break;
131 
132         ASSERT((rpos >= 0 && rpos < cb->size), "rpos is out-of-bounds: %d", rpos);
133 
134         if (rpos+avail > cb->size)
135             avail = cb->size - rpos;
136 
137         if (avail > len2)
138             avail = len2;
139 
140         memcpy( (char*)to, (const char*)cb->buff + rpos, avail );
141         to    = (char*)to + avail;
142         len2 -= avail;
143         cb->count -= avail;
144         cb->rpos  += avail;
145         if (cb->rpos >= cb->size)
146             cb->rpos -= cb->size;
147     }
148     return len - len2;
149 }
150 
151 int
cbuffer_read_peek(CBuffer * cb,uint8_t ** pbase)152 cbuffer_read_peek( CBuffer*  cb, uint8_t*  *pbase )
153 {
154     int   rpos  = cb->rpos;
155     int   avail = cb->count;
156 
157     CBUFFER_ASSERT(cb);
158 
159     if (rpos + avail > cb->size)
160         avail = cb->size - rpos;
161 
162     *pbase = cb->buff + rpos;
163     return avail;
164 }
165 
166 
167 void
cbuffer_read_step(CBuffer * cb,int len)168 cbuffer_read_step( CBuffer*  cb, int  len )
169 {
170     CBUFFER_ASSERT(cb);
171 
172     if (len > cb->count)
173         len = cb->count;
174 
175     cb->rpos  += len;
176     if (cb->rpos >= cb->size)
177         cb->rpos -= cb->size;
178 
179     cb->count -= len;
180 }
181 
182 const char*
cbuffer_quote(CBuffer * cb)183 cbuffer_quote( CBuffer*  cb )
184 {
185     STRALLOC_DEFINE(s);
186     char* q;
187 
188     stralloc_format( s, "cbuffer %p (pos=%d count=%d size=%d)",
189                      cb, cb->rpos, cb->count, cb->size );
190 
191     q = stralloc_to_tempstr( s );
192     stralloc_reset(s);
193 
194     return q;
195 }
196 
197 const char*
cbuffer_quote_data(CBuffer * cb)198 cbuffer_quote_data( CBuffer*  cb )
199 {
200     STRALLOC_DEFINE(s);
201     int   len  = cb->count;
202     int   rpos = cb->rpos;
203     char* result;
204 
205     while (len > 0) {
206         int  avail = len;
207 
208         if (rpos >= cb->size)
209             rpos -= cb->size;
210 
211         if (rpos + avail > cb->size)
212             avail = cb->size - rpos;
213 
214         stralloc_add_quote_bytes( s, cb->buff + rpos, avail );
215         rpos += avail;
216         len  -= avail;
217     }
218 
219     result = stralloc_to_tempstr(s);
220     stralloc_reset(s);
221 
222     return result;
223 }
224 
225 void
cbuffer_print(CBuffer * cb)226 cbuffer_print( CBuffer*  cb )
227 {
228     /* print the content of a cbuffer */
229     printf( "%s: %s", cbuffer_quote(cb), cbuffer_quote_data(cb) );
230 }
231 
232