Home | History | Annotate | Download | only in android
      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 "android/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
     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
     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
     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
     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
    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
    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
    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*
    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*
    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
    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