Gave aaip_0_2 a ring buffer rather than a shifted fifo

This commit is contained in:
Thomas Schmitt 2008-12-23 14:47:00 +00:00
parent ef5a1c48ba
commit 2c2a394a61
3 changed files with 282 additions and 51 deletions

View File

@ -2,7 +2,7 @@
/*
Arbitrary Attribute Interchange Protocol , AAIP version 0.2
Demonstration program for encoding and decoding EA and ACL.
Demonstration implementation of encoding and decoding EA and ACL.
See test/aaip_0_2.h
http://libburnia-project.org/wiki/AAIP
@ -184,6 +184,12 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr,
/* Not less than 2 * 2048 */
#define Aaip_buffer_sizE 4096
/* Enough for one full component record and three empty ones which might get
added in case of unclean end of attribute list.
*/
#define Aaip_buffer_reservE (257 + 3 * 2)
struct aaip_state {
/* AA field status */
@ -195,8 +201,9 @@ struct aaip_state {
/* Buffer for component records */
int recs_invalid; /* number of components to skip */
unsigned char recs[Aaip_buffer_sizE];
unsigned char recs[Aaip_buffer_sizE + Aaip_buffer_reservE];
size_t recs_fill;
unsigned char *recs_start;
int rec_head_missing; /* number of bytes needed to complete rec header */
int rec_missing; /* number of bytes needed to complete current rec */
int rec_ends;
@ -207,6 +214,7 @@ struct aaip_state {
/* Counter and meaning for completed components */
unsigned int num_components;
size_t end_of_components; /* start index of eventual incomplete component */
int first_is_name;
/* Last return value of aaip_decode_pair() */
@ -233,8 +241,9 @@ int aaip_init(struct aaip_state *aaip, char aa_name[2], int flag)
aaip->aa_missing= 0;
aaip->recs_invalid= 0;
memset(aaip->recs, 0, Aaip_buffer_sizE);
memset(aaip->recs, 0, Aaip_buffer_sizE + Aaip_buffer_reservE);
aaip->recs_fill= 0;
aaip->recs_start= aaip->recs;
aaip->rec_head_missing= 2;
aaip->rec_missing= 0;
aaip->rec_ends= 0;
@ -243,33 +252,217 @@ int aaip_init(struct aaip_state *aaip, char aa_name[2], int flag)
aaip->ready_bytes= 0;
aaip->num_components= 0;
aaip->end_of_components= 0;
aaip->first_is_name= 1;
aaip->pair_status= 1;
aaip->pair_status= 2;
aaip->pairs_skipped= 0;
return(1);
}
/*
*/
#define Aaip_with_ring_buffeR yes
#ifdef Aaip_with_ring_buffeR
/* Compute the one or two byte intervals in the ring buffer which form a
given byte interval in the virtual shift fifo.
@param idx The byte start index in the virtual shift fifo.
@param todo Number of bytes to cover
@param start_pt Will return the start address of the first interval
@param at_start_pt Will return the size of the first interval
@param at_recs Will return the size of the second interval which
always starts at aaip->recs
@param flag Bitfield for control purposes
@return 1= next start_pt is *start_pt + *at_start_pt
2= next start_pt is aaip->recs + *at_recs
*/
static int aaip_ring_adr(struct aaip_state *aaip, size_t idx, size_t todo,
unsigned char **start_pt, size_t *at_start_pt,
size_t *at_recs, int flag)
{
size_t ahead;
ahead= Aaip_buffer_sizE + Aaip_buffer_reservE
- (aaip->recs_start - aaip->recs);
if(idx < ahead)
*start_pt= (aaip->recs_start + idx);
else
*start_pt= aaip->recs + (idx - ahead);
ahead= Aaip_buffer_sizE + Aaip_buffer_reservE - (*start_pt - aaip->recs);
if(todo >= ahead) {
*at_start_pt= ahead;
*at_recs= todo - ahead;
return(2);
}
*at_start_pt= todo;
*at_recs= 0;
return(1);
}
/*
@param flag Bitfield for control purposes
bit0= count as ready_bytes
*/
static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data,
size_t todo, int flag)
{
unsigned char *start_pt;
size_t at_start_pt, at_recs;
aaip_ring_adr(aaip, aaip->recs_fill, todo,
&start_pt, &at_start_pt, &at_recs, 0);
if(at_start_pt > 0)
memcpy(start_pt, data, at_start_pt);
if(at_recs > 0)
memcpy(aaip->recs, data + at_start_pt, at_recs);
aaip->recs_fill+= todo;
if(flag & 1)
aaip->ready_bytes+= todo;
return(1);
}
static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx,
unsigned char *data, size_t num_data, int flag)
{
unsigned char *start_pt;
size_t at_start_pt, at_recs;
aaip_ring_adr(aaip, idx, num_data,
&start_pt, &at_start_pt, &at_recs, 0);
if(at_start_pt > 0)
memcpy(data, start_pt, at_start_pt);
if(at_recs > 0)
memcpy(data + at_start_pt, aaip->recs, at_recs);
return(1);
}
static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx,
unsigned char data, int flag)
{
unsigned char *start_pt;
size_t at_start_pt, at_recs;
aaip_ring_adr(aaip, idx, 1,
&start_pt, &at_start_pt, &at_recs, 0);
*start_pt= data;
return(1);
}
static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag)
{
unsigned char *start_pt;
size_t at_start_pt, at_recs;
aaip_ring_adr(aaip, idx, 1,
&start_pt, &at_start_pt, &at_recs, 0);
return((int) *start_pt);
}
static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag)
{
int ret;
unsigned char *start_pt;
size_t at_start_pt, at_recs;
if(todo < aaip->recs_fill) {
ret= aaip_ring_adr(aaip, 0, todo, &start_pt, &at_start_pt, &at_recs, 0);
if(ret == 1)
aaip->recs_start= start_pt + todo;
else
aaip->recs_start= aaip->recs + at_recs;
} else {
aaip->recs_start= aaip->recs;
}
aaip->recs_fill-= todo;
if(aaip->end_of_components >= todo)
aaip->end_of_components-= todo;
else
aaip->end_of_components= 0;
return(1);
}
#else /* Aaip_with_ring_buffeR */
/*
@param flag Bitfield for control purposes
bit0= count as ready_bytes
*/
static int aaip_push_to_recs(struct aaip_state *aaip, unsigned char *data,
size_t todo, int flag)
{
memcpy(aaip->recs + aaip->recs_fill, data, todo);
aaip->recs_fill+= todo;
if(flag & 1)
aaip->ready_bytes+= todo;
return(1);
}
static int aaip_read_from_recs(struct aaip_state *aaip, size_t idx,
unsigned char *data, size_t num_data, int flag)
{
memcpy(data, aaip->recs + idx, num_data);
return(1);
}
static int aaip_set_buffer_byte(struct aaip_state *aaip, size_t idx,
unsigned char data, int flag)
{
aaip->recs[idx]= data;
return(1);
}
static int aaip_get_buffer_byte(struct aaip_state *aaip, size_t idx, int flag)
{
return((int) aaip->recs[idx]);
}
static int aaip_shift_recs(struct aaip_state *aaip, size_t todo, int flag)
{
if(todo < aaip->recs_fill)
memmove(aaip->recs, aaip->recs + todo, aaip->recs_fill - todo);
aaip->recs_fill-= todo;
if(aaip->end_of_components >= todo)
aaip->end_of_components-= todo;
else
aaip->end_of_components= 0;
return(1);
}
#endif /* ! Aaip_with_ring_buffeR */
static int aaip_consume_rec_head(struct aaip_state *aaip,
unsigned char **data, size_t *num_data, int flag)
{
size_t todo, i;
size_t todo;
todo= *num_data;
if(todo > aaip->aa_missing)
todo= aaip->aa_missing;
if(todo >= aaip->rec_head_missing)
todo= aaip->rec_head_missing;
if(!aaip->recs_invalid) {
memcpy(aaip->recs + aaip->recs_fill, *data + i, todo);
aaip->recs_fill+= todo;
}
if(!aaip->recs_invalid)
aaip_push_to_recs(aaip, *data, todo, 0);
aaip->rec_head_missing-= todo;
if(aaip->rec_head_missing == 0) {
aaip->rec_missing= aaip->recs[aaip->recs_fill - 1];
aaip->rec_ends= !(aaip->recs[aaip->recs_fill - 2] & 1);
aaip->rec_missing= aaip_get_buffer_byte(aaip, aaip->recs_fill - 1, 0);
aaip->rec_ends= !(aaip_get_buffer_byte(aaip, aaip->recs_fill - 2, 0) & 1);
}
aaip->aa_missing-= todo;
(*num_data)-= todo;
@ -281,18 +474,15 @@ static int aaip_consume_rec_head(struct aaip_state *aaip,
static int aaip_consume_rec_data(struct aaip_state *aaip,
unsigned char **data, size_t *num_data, int flag)
{
size_t todo, i;
size_t todo;
todo= *num_data;
if(todo > aaip->aa_missing)
todo= aaip->aa_missing;
if(todo > aaip->rec_missing)
todo= aaip->rec_missing;
if(!aaip->recs_invalid) {
memcpy(aaip->recs + aaip->recs_fill, *data + i, todo);
aaip->recs_fill+= todo;
aaip->ready_bytes+= todo;
}
if(!aaip->recs_invalid)
aaip_push_to_recs(aaip, *data, todo, 1);
aaip->rec_missing-= todo;
aaip->aa_missing-= todo;
(*num_data)-= todo;
@ -303,8 +493,10 @@ static int aaip_consume_rec_data(struct aaip_state *aaip,
aaip->recs_invalid--;
} else {
aaip->num_recs++;
if(aaip->rec_ends)
if(aaip->rec_ends) {
aaip->num_components++;
aaip->end_of_components= aaip->recs_fill;
}
}
aaip->rec_head_missing= 2;
}
@ -315,21 +507,21 @@ static int aaip_consume_rec_data(struct aaip_state *aaip,
static int aaip_consume_aa_head(struct aaip_state *aaip,
unsigned char **data, size_t *num_data, int flag)
{
size_t todo, i;
size_t todo;
unsigned char aa_head[5];
todo= *num_data;
if(todo >= aaip->aa_head_missing)
todo= aaip->aa_head_missing;
for(i= 0; i < todo; i++)
aaip->recs[aaip->recs_fill++]= (*data)[i];
aaip_push_to_recs(aaip, *data, todo, 0);
aaip->aa_head_missing-= todo;
if(aaip->aa_head_missing == 0) {
if(aaip->recs[aaip->recs_fill - 5] != aaip->aa_name[0] ||
aaip->recs[aaip->recs_fill - 4] != aaip->aa_name[1] ||
aaip->recs[aaip->recs_fill - 2] != 1)
aaip_read_from_recs(aaip, aaip->recs_fill - 5, aa_head, 5, 0);
if(aa_head[0] != aaip->aa_name[0] || aa_head[1] != aaip->aa_name[1] ||
aa_head[3] != 1)
return(-1);
aaip->aa_missing= aaip->recs[aaip->recs_fill - 3];
aaip->aa_ends= !(aaip->recs[aaip->recs_fill - 1] & 1);
aaip->aa_missing= aa_head[2];
aaip->aa_ends= !(aa_head[4] & 1);
aaip->recs_fill-= 5; /* AA heads do not get delivered */
if(aaip->aa_missing >= 5)
aaip->aa_missing-= 5;
@ -345,6 +537,9 @@ static int aaip_consume_aa_head(struct aaip_state *aaip,
static int aaip_consume_aa_data(struct aaip_state *aaip,
unsigned char **data, size_t *num_data, int flag)
{
size_t i;
static unsigned char zero_char[2]= {0, 0};
while(*num_data > 0 && aaip->aa_missing > 0) {
if(aaip->rec_head_missing > 0) {
aaip_consume_rec_head(aaip, data, num_data, 0);
@ -355,9 +550,42 @@ static int aaip_consume_aa_data(struct aaip_state *aaip,
}
if(aaip->aa_missing <= 0) {
if(aaip->aa_ends) {
/* >>> Check for incomplete component or pair, discard it */;
/* Check for incomplete pair and eventually make emergency closure */
if(aaip->rec_head_missing != 2) { /* incomplete record detected */
if(aaip->rec_head_missing) {
/* fake 0 length record */
aaip_set_buffer_byte(aaip, aaip->recs_fill - 1, (unsigned char) 0, 0);
aaip_push_to_recs(aaip, zero_char, 1, 0);
} else {
/* fill in missing btes */
for(i= 0; i < aaip->rec_missing; i++)
aaip_push_to_recs(aaip, zero_char, 1, 1);
}
aaip->rec_head_missing= 2;
aaip->rec_missing= 0;
aaip->num_recs++;
if(aaip->rec_ends) {
aaip->num_components++;
aaip->end_of_components= aaip->recs_fill;
}
}
if(aaip->end_of_components != aaip->recs_fill &&
aaip->end_of_components != 0) {
/* incomplete component detected */
/* add empty end record */
aaip_push_to_recs(aaip, zero_char, 2, 0);
aaip->num_recs++;
aaip->num_components++;
aaip->end_of_components= aaip->recs_fill;
}
if(!(aaip->first_is_name ^ (aaip->num_components % 2))) {
/* value component is missing */
/* add dummy component */
aaip_push_to_recs(aaip, zero_char, 2, 0);
aaip->num_recs++;
aaip->num_components++;
aaip->end_of_components= aaip->recs_fill;
}
aaip->aa_ends= 2;
} else
aaip->aa_head_missing= 5;
@ -397,7 +625,7 @@ int aaip_submit_data(struct aaip_state *aaip,
if(aaip->recs_fill + num_data > Aaip_buffer_sizE)
return(0);
while(aaip->aa_missing == 0 && num_data > 0) {
while(num_data > 0) {
if(aaip->aa_head_missing > 0) {
ret= aaip_consume_aa_head(aaip, &data, &num_data, 0);
if(ret < 0) {
@ -408,6 +636,8 @@ int aaip_submit_data(struct aaip_state *aaip,
goto ex;
}
aaip_consume_aa_data(aaip, &data, &num_data, 0);
if(aaip->aa_missing)
break;
}
ex:;
*ready_bytes= aaip->ready_bytes;
@ -445,7 +675,7 @@ int aaip_fetch_data(struct aaip_state *aaip,
char *result, size_t result_size, size_t *num_result,
int flag)
{
int ret= -1, complete= 0;
int ret= -1, complete= 0, payload;
unsigned int i, num_bytes= 0, h;
if(aaip->num_recs == 0)
@ -454,24 +684,24 @@ int aaip_fetch_data(struct aaip_state *aaip,
/* Copy data until end of buffer or end of component */
h= 0;
for(i= 0; i < aaip->num_recs && !complete; i++) {
payload= aaip_get_buffer_byte(aaip, h + 1, 0);
if(!(flag & 1)) {
if(num_bytes + aaip->recs[h + 1] > result_size)
if(num_bytes + payload > result_size)
return(-2);
memcpy(result + num_bytes, aaip->recs + h + 2, aaip->recs[h + 1]);
*num_result= num_bytes + aaip->recs[h + 1];
aaip_read_from_recs(aaip, h + 2, (unsigned char *) (result + num_bytes),
payload, 0);
*num_result= num_bytes + payload;
}
num_bytes+= aaip->recs[h + 1];
if(!(aaip->recs[h] & 1))
num_bytes+= payload;
if(!(aaip_get_buffer_byte(aaip, h, 0) & 1))
complete= 1;
h+= aaip->recs[h + 1] + 2;
h+= payload + 2;
}
aaip->num_recs-= i;
aaip->ready_bytes-= num_bytes;
aaip->num_recs-= i;
/* Shift buffer */
if(h < aaip->recs_fill)
memmove(aaip->recs, aaip->recs + h, aaip->recs_fill - h);
aaip->recs_fill-= h;
aaip_shift_recs(aaip, h, 0);
/* Compute reply */
ret= 2 * !aaip->first_is_name;
@ -500,12 +730,12 @@ int aaip_skip_component(struct aaip_state *aaip, int flag)
{
int to_skip= 1;
if(aaip->recs_invalid) {
aaip->recs_invalid+= 1 + (flag & 1);
return(1);
}
if(aaip->first_is_name && !(flag & 1))
to_skip= 2;
if(aaip->recs_invalid) {
aaip->recs_invalid+= to_skip;
return(1);
}
if(aaip->num_components) {
/* null-fetch */

View File

@ -168,6 +168,7 @@ int aaip_skip_component(struct aaip_state *aaip, int flag);
3 name and value are valid, pairs pending, fetch with num_data == 0
4 name and value are valid, no more data expected
5 name and value are not valid, no more data expected
*/
int aaip_decode_pair(struct aaip_state *aaip,
unsigned char *data, size_t num_data, size_t *consumed,

View File

@ -26,6 +26,8 @@
#include "aaip_0_2.h"
#define Aaip_test_name_sizE 1024
#define Aaip_test_value_sizE 1024
int main(int argc, char **argv)
{
@ -37,11 +39,9 @@ int main(int argc, char **argv)
struct aaip_state *aaip;
size_t consumed= 0;
char name[1025];
size_t name_size= 4;
char name[Aaip_test_name_sizE + 1];
size_t name_fill;
char value[1025];
size_t value_size= 1024;
char value[Aaip_test_value_sizE + 1];
size_t value_fill;
size_t todo;
int submit_data, is_done;
@ -126,8 +126,8 @@ int main(int argc, char **argv)
} else
todo= 0;
ret= aaip_decode_pair(aaip, rpt, todo, &consumed,
name, name_size, &name_fill,
value, value_size, &value_fill, 0);
name, Aaip_test_name_sizE, &name_fill,
value, Aaip_test_value_sizE, &value_fill, 0);
skipped= aaip_get_pairs_skipped(aaip, 0);
if(skipped > was_skipped) {
printf("- skipped %d pair%s -\n\n", skipped - was_skipped,