/* Copyright (C) 2007-2008 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ #include "cbuffer.h" #include "android/utils/stralloc.h" #include <string.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> #define DEBUG 0 #if DEBUG # define ASSERT(cond,fmt,...) ({ if (!(cond)) { fprintf(stderr, fmt, __VA_ARGS__); assert(cond); } }) #else # define ASSERT(cond,fmt,...) ((void)0) #endif #if DEBUG void cbuffer_assert( CBuffer* cb, const char* file, long lineno ) { const char* reason = NULL; if (cb->rpos < 0 || cb->rpos >= cb->size) { reason = "rpos is out of bounds"; } else if (cb->count < 0 || cb->count > cb->size) { reason = "count is incorrect"; } if (!reason) return; fprintf(stderr, "assert:%s:%ld: assertion failed: %s (pos=%d count=%d size=%d)\n", file, lineno, reason, cb->rpos, cb->count, cb->size); assert(0); } # define CBUFFER_ASSERT(cb) cbuffer_assert(cb,__FUNCTION__,__LINE__) #else # define CBUFFER_ASSERT(cb) ((void)0) #endif int cbuffer_write_peek( CBuffer* cb, uint8_t* *pbase ) { int wpos = cb->rpos + cb->count; int avail = cb->size - cb->count; CBUFFER_ASSERT(cb); if (wpos >= cb->size) wpos -= cb->size; if (wpos + avail > cb->size) avail = cb->size - wpos; *pbase = cb->buff + wpos; return avail; } void cbuffer_write_step( CBuffer* cb, int len ) { CBUFFER_ASSERT(cb); cb->count += len; if (cb->count > cb->size) cb->count = cb->size; } int cbuffer_write( CBuffer* cb, const void* from, int len ) { int len2 = len; CBUFFER_ASSERT(cb); while (len2 > 0) { int avail = cb->size - cb->count; int wpos = cb->rpos + cb->count; ASSERT(avail >= 0, "avail is negative: %d", avail); if (avail == 0) break; if (wpos >= cb->size) wpos -= cb->size; ASSERT( wpos >= 0 && wpos < cb->size, "wpos is out-of-bounds: %d (rpos=%d)", wpos, cb->rpos); if (wpos + avail > cb->size) avail = cb->size - wpos; if (avail > len2) avail = len2; memcpy( cb->buff + wpos, (const char*)from, avail ); from = (char*)from + avail; len2 -= avail; cb->count += avail; } return len - len2; } int cbuffer_read( CBuffer* cb, void* to, int len ) { int len2 = len; CBUFFER_ASSERT(cb); while (len2 > 0) { int avail = cb->count; int rpos = cb->rpos; ASSERT(avail >= 0, "avail is negative: %d", avail); if (avail == 0) break; ASSERT((rpos >= 0 && rpos < cb->size), "rpos is out-of-bounds: %d", rpos); if (rpos+avail > cb->size) avail = cb->size - rpos; if (avail > len2) avail = len2; memcpy( (char*)to, (const char*)cb->buff + rpos, avail ); to = (char*)to + avail; len2 -= avail; cb->count -= avail; cb->rpos += avail; if (cb->rpos >= cb->size) cb->rpos -= cb->size; } return len - len2; } int cbuffer_read_peek( CBuffer* cb, uint8_t* *pbase ) { int rpos = cb->rpos; int avail = cb->count; CBUFFER_ASSERT(cb); if (rpos + avail > cb->size) avail = cb->size - rpos; *pbase = cb->buff + rpos; return avail; } void cbuffer_read_step( CBuffer* cb, int len ) { CBUFFER_ASSERT(cb); if (len > cb->count) len = cb->count; cb->rpos += len; if (cb->rpos >= cb->size) cb->rpos -= cb->size; cb->count -= len; } const char* cbuffer_quote( CBuffer* cb ) { STRALLOC_DEFINE(s); char* q; stralloc_format( s, "cbuffer %p (pos=%d count=%d size=%d)", cb, cb->rpos, cb->count, cb->size ); q = stralloc_to_tempstr( s ); stralloc_reset(s); return q; } const char* cbuffer_quote_data( CBuffer* cb ) { STRALLOC_DEFINE(s); int len = cb->count; int rpos = cb->rpos; char* result; while (len > 0) { int avail = len; if (rpos >= cb->size) rpos -= cb->size; if (rpos + avail > cb->size) avail = cb->size - rpos; stralloc_add_quote_bytes( s, cb->buff + rpos, avail ); rpos += avail; len -= avail; } result = stralloc_to_tempstr(s); stralloc_reset(s); return result; } void cbuffer_print( CBuffer* cb ) { /* print the content of a cbuffer */ printf( "%s: %s", cbuffer_quote(cb), cbuffer_quote_data(cb) ); }