Gave aaip_0_2 a ring buffer rather than a shifted fifo
This commit is contained in:
parent
ef5a1c48ba
commit
2c2a394a61
320
test/aaip_0_2.c
320
test/aaip_0_2.c
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user