00001
00007 #include "ctl/ctldef.h"
00008 #include "ctl/debug.h"
00009 #include "ctl/ctlnew.h"
00010 #include "ctl/ringbuff.h"
00011
00012 #ifndef CTL_UNIT
00013
00020 void RingBuff_Init( RingBuff* self, void* buff, size_t size )
00021 {
00022 assertobjptr(self);
00023 assertptr(buff,size);
00024 self->buff = (const uint8*)buff;
00025 self->end = self->buff + size;
00026 self->head = self->tail = (uint8*)self->buff;
00027 }
00028
00036 bool RingBuff_Space( RingBuff* self, uint8** buff, size_t count )
00037 {
00038 assertobjconst(self);
00039 assert( self->head <= self->tail );
00040 if( self->tail + count <= self->end )
00041 {
00042 *buff = (uint8*)self->tail;
00043 return true;
00044 }
00045 else if( self->head > self->buff && (count <= RingBuff_Free(self) ) )
00046 {
00047 size_t used = self->tail - self->head;
00048 memmove( (uint8*)self->buff, self->head, used );
00049 self->head = (uint8*)self->buff;
00050 self->tail = (uint8*)self->buff + used;
00051 *buff = (uint8*)self->tail;
00052 return true;
00053 }
00054 *buff = NULL;
00055 return false;
00056 }
00057
00065 bool RingBuff_Peek( RingBuff* self, const uint8** buff, size_t count )
00066 {
00067 assertobjptr(self);
00068 assert( self->tail >= self->head );
00069 if( self->head + count > self->tail )
00070 {
00071 return false;
00072 }
00073 *buff = self->head;
00074 return true;
00075 }
00076
00083 bool RingBuff_Consume( RingBuff* self, size_t count )
00084 {
00085 assertobjptr(self);
00086 assert( self->tail >= self->head );
00087 if( self->head + count > self->tail )
00088 {
00089 return false;
00090 }
00091 self->head += count;
00092 if( self->head == self->tail )
00093 {
00094 RingBuff_Reset(self);
00095 }
00096 return true;
00097 }
00098
00105 bool RingBuff_Add( RingBuff* self, uint8** buff, size_t count )
00106 {
00107 if( RingBuff_Space( self, buff, count ) )
00108 {
00109 self->tail += count;
00110 return true;
00111 }
00112 return false;
00113 }
00114
00121 bool RingBuff_Pop( RingBuff* self, const uint8** buff, size_t count )
00122 {
00123 if( RingBuff_Peek( self, buff, count ) )
00124 {
00125 self->head += count;
00126 if( self->head == self->tail )
00127 {
00128 RingBuff_Reset(self);
00129 }
00130 return true;
00131 }
00132
00133 return false;
00134 }
00135
00143 bool RingBuff_CopyTo( RingBuff* self, const void* buff, size_t count )
00144 {
00145 uint8* space;
00146 if( RingBuff_Space( self, &space, count ) )
00147 {
00148 memcpy(space,buff,count);
00149 self->tail += count;
00150 return true;
00151 }
00152 return false;
00153 }
00154
00162 bool RingBuff_CopyFrom( RingBuff* self, void* buff, size_t count )
00163 {
00164 const uint8* data;
00165 if( RingBuff_Peek( self, &data, count ) )
00166 {
00167 memcpy(buff,data,count);
00168 self->head += count;
00169 return true;
00170 }
00171 return false;
00172 }
00173
00182 bool RingBuff_AddSerial( RingBuff* self, ctl_serial* serial, size_t reserve )
00183 {
00184 uint8* space;
00185 uint16 size = 2 + reserve;
00186 if( RingBuff_Add( self, &space, size ) )
00187 {
00188 ctl_serial_init( serial, space, space + size );
00189 uint16_serial_write(&size, serial );
00190 return true;
00191 }
00192 return false;
00193 }
00194
00202 bool RingBuff_PeekSerial( RingBuff* self, ctl_serial* serial )
00203 {
00204 const uint8* data;
00205 if( RingBuff_Peek( self, &data, 2 ) )
00206 {
00207 ctl_serial_init( serial, (uint8*)data, data+2 );
00208 uint16 size;
00209 uint16_serial_read(&size, serial );
00210 ctl_serial_init( serial, data, data + size );
00211 return true;
00212 }
00213 return false;
00214 }
00215
00223 bool RingBuff_PopSerial( RingBuff* self, ctl_serial* serial )
00224 {
00225 const uint8* data;
00226 if( RingBuff_Peek( self, &data, 2 ) )
00227 {
00228 uint16 size;
00229 ctl_serial_init( serial, data, data+2 );
00230 uint16_serial_read(&size, serial );
00231
00232 if( RingBuff_Pop( self, &data, size ) )
00233 {
00234 ctl_serial_init( serial, data, data + size );
00235
00236 serial->curr += 2;
00237 return true;
00238 }
00239 }
00240 return false;
00241 }
00242
00243
00244 #else
00245
00246 #include "unit/unit.h"
00247
00248 void Test_RingBuff1(void);
00249 void Test_RingBuff2(void);
00250 void Test_RingBuff3(void);
00251 void Test_RingBuff4(void);
00252 void Test_RingBuff5(void);
00253
00254 void Test_RingBuff(void)
00255 {
00256
00257 Test_RingBuff1();
00258 Test_RingBuff2();
00259 Test_RingBuff3();
00260 Test_RingBuff4();
00261 Test_RingBuff5();
00262 }
00263
00264
00265
00266
00267 void Test_RingBuff1(void)
00268 {
00269 RingBuff rb;
00270 uint8 buffer[16];
00271 #define RINGBUFF_AVAIL sizeof(buffer)
00272 const uint8* read;
00273 uint8* write;
00274 uint8* scratch = buffer;
00275 RingBuff_Init(&rb,buffer,sizeof(buffer));
00276
00277
00278 Test_Error( RINGBUFF_AVAIL == RingBuff_Total(&rb) );
00279 Test_Error( RINGBUFF_AVAIL == RingBuff_Free(&rb) );
00280 Test_Error( 0 == RingBuff_Remain(&rb) );
00281
00282
00283 Test_Error( RingBuff_Add( &rb, &write, 2 ) );
00284 Test_Error( scratch == buffer );
00285 Test_Error( buffer == write );
00286 memcpy(write,"HI",2);
00287 Test_Error( RINGBUFF_AVAIL-2 == RingBuff_Free(&rb) );
00288 Test_Error( 2 == RingBuff_Remain(&rb) );
00289
00290
00291 Test_Error( !RingBuff_Peek( &rb, &read, 3 ) );
00292
00293
00294 Test_Error( RingBuff_Peek( &rb, &read, 2 ) );
00295 Test_Error( 0 == memcmp(read,"HI",2) );
00296 Test_Error( RingBuff_Pop( &rb, &read, 2 ) );
00297 Test_Error( 0 == memcmp(read,"HI",2) );
00298 Test_Error( RINGBUFF_AVAIL == RingBuff_Free(&rb) );
00299 Test_Error( 0 == RingBuff_Remain(&rb) );
00300
00301
00302 Test_Error( RingBuff_Add( &rb, &write, 5 ) );
00303 memcpy(write,"12345",5);
00304 Test_Error( RINGBUFF_AVAIL-5 == RingBuff_Free(&rb) );
00305 Test_Error( 5 == RingBuff_Remain(&rb) );
00306 Test_Error( RingBuff_Add( &rb, &write, 5 ) );
00307 memcpy(write,"ABCDE",5);
00308 Test_Error( RINGBUFF_AVAIL-10 == RingBuff_Free(&rb) );
00309 Test_Error( 10 == RingBuff_Remain(&rb) );
00310
00311
00312 Test_Error( !RingBuff_Add( &rb, &write, 7 ) );
00313 Test_Error( NULL == write );
00314 Test_Error( RINGBUFF_AVAIL-10 == RingBuff_Free(&rb) );
00315 Test_Error( 10 == RingBuff_Remain(&rb) );
00316
00317
00318 Test_Error( RingBuff_Add( &rb, &write, 6 ) );
00319 memcpy(write,"654321",6);
00320 Test_Error( 0 == RingBuff_Free(&rb) );
00321 Test_Error( 16 == RingBuff_Remain(&rb) );
00322
00323
00324 Test_Error( RingBuff_Pop( &rb, &read, 5 ) );
00325 Test_Error( 0 == memcmp(read,"12345",5) );
00326 Test_Error( RINGBUFF_AVAIL-11 == RingBuff_Free(&rb) );
00327 Test_Error( 11 == RingBuff_Remain(&rb) );
00328
00329
00330 Test_Error( !RingBuff_Peek( &rb, &read, 12 ) );
00331 Test_Error( !RingBuff_Pop( &rb, &read, 12 ) );
00332
00333
00334 Test_Error( RingBuff_Add( &rb, &write, 5 ) );
00335 memcpy(write,"ZYXWV",5);
00336 Test_Error( 0 == RingBuff_Free(&rb) );
00337 Test_Error( RINGBUFF_AVAIL == RingBuff_Remain(&rb) );
00338
00339
00340 Test_Error( RingBuff_Pop( &rb, &read, 5 ) );
00341 Test_Error( 0 == memcmp(read,"ABCDE",5) );
00342 Test_Error( 5 == RingBuff_Free(&rb) );
00343 Test_Error( 11 == RingBuff_Remain(&rb) );
00344
00345
00346 Test_Error( !RingBuff_Add( &rb, &write, 11 ) );
00347 Test_Error( 5 == RingBuff_Free(&rb) );
00348 Test_Error( 11 == RingBuff_Remain(&rb) );
00349
00350
00351 Test_Error( RingBuff_Add( &rb, &write, 5 ) );
00352 memcpy(write,"!@#$%^",5);
00353 Test_Error( 0 == RingBuff_Free(&rb) );
00354 Test_Error( 16 == RingBuff_Remain(&rb) );
00355
00356
00357 RingBuff_Pop( &rb, &read, 10 );
00358 Test_Error( 0 == memcmp(read,"654321ZYXWV",10) );
00359 Test_Error( 6 == RingBuff_Remain(&rb) );
00360 Test_Error( 10 == RingBuff_Free(&rb) );
00361 RingBuff_Add( &rb, &write, 3 );
00362 memcpy(write,"123",3);
00363 Test_Error( 7 == RingBuff_Free(&rb) );
00364 Test_Error( 9 == RingBuff_Remain(&rb) );
00365
00366 }
00367
00368
00369
00370
00371
00372 void Test_RingBuff2(void)
00373 {
00374 RingBuff rb1;
00375 uint8 buffer1[64];
00376 RingBuff rb2;
00377 uint8 buffer2[64];
00378 RingBuff_Init(&rb1,buffer1,sizeof(buffer1));
00379 RingBuff_Init(&rb2,buffer2,sizeof(buffer2));
00380
00381
00382
00383
00384 while( 3 < RingBuff_Free(&rb1) )
00385 {
00386 uint8* p;
00387 Test_Error( RingBuff_Add( &rb1, &p, 1 ) );
00388 *p = uint8_rand();
00389 }
00390 Test_Error( 3 == RingBuff_Free(&rb1) );
00391 Test_Error( 61 == RingBuff_Remain(&rb1) );
00392 {
00393 uint8* write;
00394 const uint8* read;
00395 Test_Error( RingBuff_Add( &rb2, &write, 5 ) );
00396 Test_Error( RingBuff_CopyFrom( &rb1, write, 5 ) );
00397 Test_Error( 8 == RingBuff_Free(&rb1) );
00398 Test_Error( 56 == RingBuff_Remain(&rb1) );
00399 Test_Error( 59 == RingBuff_Free(&rb2) );
00400 Test_Error( 5 == RingBuff_Remain(&rb2) );
00401
00402 Test_Error(RingBuff_Pop( &rb2, &read, 5 ));
00403 Test_Error( RingBuff_CopyTo( &rb1, read, 5 ) );
00404
00405 Test_Error( 3 == RingBuff_Free(&rb1) );
00406 Test_Error( 61 == RingBuff_Remain(&rb1) );
00407 Test_Error( RingBuff_IsEmpty( &rb2 ) );
00408 }
00409 }
00410
00411 struct test
00412 {
00413 int32 a, b, c;
00414 };
00415
00416
00417
00418 void Test_RingBuff3(void)
00419 {
00420 struct test test1, test2;
00421 RingBuff rb;
00422 uint8 buffer[64];
00423 ctl_serial serial;
00424 RingBuff_Init(&rb,buffer,sizeof(buffer));
00425 test1.a = rand();
00426 test1.b = rand();
00427 test1.c = rand();
00428 Test_Error( RingBuff_AddSerial( &rb, &serial, 12 ) );
00429 int32_serial_write( &test1.a, &serial );
00430 int32_serial_write( &test1.b, &serial );
00431 int32_serial_write( &test1.c, &serial );
00432 Test_Error( RingBuff_PopSerial( &rb, &serial ) );
00433 int32_serial_read( &test2.a, &serial );
00434 int32_serial_read( &test2.b, &serial );
00435 int32_serial_read( &test2.c, &serial );
00436 Test_Error( test1.a == test2.a && test1.b == test2.b && test1.c == test2.c );
00437 }
00438
00439 #define RAND_TEST_ITERATIONS 1000
00440
00441
00442
00443
00444
00445
00446 void Test_RingBuff4(void)
00447 {
00448 int times = RAND_TEST_ITERATIONS;
00449 RingBuff rb;
00450 uint8 buffer[64];
00451 uint8 seq = 0;
00452 uint8 seqpop = 0;
00453 RingBuff_Init(&rb,buffer,sizeof(buffer));
00454 while( times-- )
00455 {
00456 size_t size = RingBuff_Free( &rb );
00457 size_t todo = size * rand() / RAND_MAX;
00458 const uint8* popped;
00459 uint8* pcurr;
00460 if( !RingBuff_Add( &rb, &pcurr, todo ) )
00461 {
00462 size = RingBuff_Free( &rb );
00463 todo = size * rand() / RAND_MAX;
00464 Test_Error(RingBuff_Add( &rb, &pcurr, todo ));
00465 }
00466 while( todo-- )
00467 {
00468 *pcurr++ = seq++;
00469 }
00470 size = RingBuff_Remain( &rb );
00471 todo = size * rand() / RAND_MAX;
00472 Test_Error(RingBuff_Pop( &rb, &popped, todo ));
00473 while( todo-- )
00474 {
00475 Test_Error( *popped++ == seqpop++ );
00476 }
00477 }
00478 }
00479
00480
00481
00482
00483
00484
00485 void Test_RingBuff5(void)
00486 {
00487 int times = RAND_TEST_ITERATIONS;
00488 RingBuff rb;
00489 uint8 buffer[64];
00490 uint8 seq = 0;
00491 uint8 seqpop = 0;
00492 RingBuff_Init(&rb,buffer,sizeof(buffer));
00493 while( times-- )
00494 {
00495 size_t size = RingBuff_Free( &rb )-2;
00496 size_t todo = size * rand() / RAND_MAX;
00497 ctl_serial serial;
00498 Test_Error(RingBuff_AddSerial( &rb, &serial, todo ));
00499 while( serial.curr < serial.end )
00500 {
00501 *serial.curr++ = seq++;
00502 }
00503 Test_Error(RingBuff_PopSerial( &rb, &serial ));
00504 while( serial.curr < serial.end )
00505 {
00506 Test_Error( *serial.curr++ == seqpop++ );
00507 }
00508 }
00509 }
00510
00511
00512 #endif
00513