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