1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* Copyright (C) 2007-2008 The Android Open Source Project
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert**
3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** This software is licensed under the terms of the GNU General Public
4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** License version 2, as published by the Free Software Foundation, and
5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** may be copied, distributed, and modified under those terms.
6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson**
7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** This program is distributed in the hope that it will be useful,
8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** but WITHOUT ANY WARRANTY; without even the implied warranty of
9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson** GNU General Public License for more details.
11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson*/
12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "android/cbuffer.h"
13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include "android/utils/stralloc.h"
14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include <string.h>
15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include <stdlib.h>
16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include <assert.h>
17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#include <stdio.h>
18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#define  DEBUG  0
20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#if DEBUG
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#  define  ASSERT(cond,fmt,...)  ({ if (!(cond)) { fprintf(stderr, fmt, __VA_ARGS__); assert(cond); } })
23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#else
24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#  define  ASSERT(cond,fmt,...)  ((void)0)
25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#endif
26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#if DEBUG
28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonvoid
29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_assert( CBuffer*  cb, const char*  file, long  lineno )
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    const char*  reason = NULL;
32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (cb->rpos < 0 || cb->rpos >= cb->size) {
34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        reason = "rpos is out of bounds";
35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    else if (cb->count < 0 || cb->count > cb->size) {
37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        reason = "count is incorrect";
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (!reason)
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return;
41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    fprintf(stderr, "assert:%s:%ld: assertion failed: %s (pos=%d count=%d size=%d)\n",
43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            file, lineno, reason, cb->rpos, cb->count, cb->size);
44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    assert(0);
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#  define  CBUFFER_ASSERT(cb)  cbuffer_assert(cb,__FUNCTION__,__LINE__)
47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#else
48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#  define  CBUFFER_ASSERT(cb)  ((void)0)
49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson#endif
50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonint
52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_write_peek( CBuffer*  cb, uint8_t*  *pbase )
53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int  wpos  = cb->rpos + cb->count;
55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int  avail = cb->size - cb->count;
56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (wpos >= cb->size)
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        wpos -= cb->size;
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (wpos + avail > cb->size)
63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        avail = cb->size - wpos;
64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    *pbase = cb->buff + wpos;
66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return avail;
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid
70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_write_step( CBuffer*  cb, int  len )
71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    cb->count += len;
75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (cb->count > cb->size)
76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        cb->count = cb->size;
77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonint
81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_write( CBuffer*  cb, const void*  from, int  len )
82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int  len2 = len;
84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    while (len2 > 0) {
88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        int  avail = cb->size - cb->count;
89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        int  wpos  = cb->rpos + cb->count;
90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        ASSERT(avail >= 0, "avail is negative: %d", avail);
92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (avail == 0)
94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            break;
95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (wpos >= cb->size)
97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            wpos -= cb->size;
98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        ASSERT( wpos >= 0 && wpos < cb->size, "wpos is out-of-bounds: %d (rpos=%d)", wpos, cb->rpos);
100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (wpos + avail > cb->size)
102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            avail = cb->size - wpos;
103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (avail > len2)
105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            avail = len2;
106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        memcpy( cb->buff + wpos, (const char*)from, avail );
108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        from  = (char*)from + avail;
110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        len2 -= avail;
111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        cb->count += avail;
112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return len - len2;
114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonint
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertcbuffer_read( CBuffer*  cb, void*  to, int  len )
118090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
119090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int   len2 = len;
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    while (len2 > 0) {
124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        int  avail = cb->count;
125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        int  rpos = cb->rpos;
126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
127090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        ASSERT(avail >= 0, "avail is negative: %d", avail);
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
129090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (avail == 0)
130090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            break;
131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        ASSERT((rpos >= 0 && rpos < cb->size), "rpos is out-of-bounds: %d", rpos);
133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (rpos+avail > cb->size)
135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            avail = cb->size - rpos;
136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (avail > len2)
138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            avail = len2;
139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        memcpy( (char*)to, (const char*)cb->buff + rpos, avail );
141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        to    = (char*)to + avail;
142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        len2 -= avail;
143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        cb->count -= avail;
144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        cb->rpos  += avail;
145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        if (cb->rpos >= cb->size)
146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson            cb->rpos -= cb->size;
147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return len - len2;
149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertint
152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_read_peek( CBuffer*  cb, uint8_t*  *pbase )
153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int   rpos  = cb->rpos;
155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int   avail = cb->count;
156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (rpos + avail > cb->size)
160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        avail = cb->size - rpos;
161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
162090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    *pbase = cb->buff + rpos;
163090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return avail;
164090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
165090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
166090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
167090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonvoid
168090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsoncbuffer_read_step( CBuffer*  cb, int  len )
169090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson{
170090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    CBUFFER_ASSERT(cb);
171090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
172090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (len > cb->count)
173090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        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
182const char*
183cbuffer_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
197const char*
198cbuffer_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
225void
226cbuffer_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