Changed lfsr_data_t internals, added LFSR_DATA_CAT
The main purpose of this change is to introduce LFSR_DATA_CAT, a
generalized way to concatenated various data references internally.
As a side-effect lfsr_data_t has been completely restructured. Now,
lfsr_data_t can be in one of 4 modes:
If the size field's sign bit=0, the lfsr_data_t points in-device. A new,
count field, determines the encoding:
sign(size)=0, count=0 => inlined:
.---+---+---+---.
| size |
|---+---+---+---|
|c=0| inlined d | note inlined data is just enough to hold
|---+ | one encoded leb128
| ata... |
'---------------'
sign(size)=1, count=1 => direct:
.---+---+---+---. .---+---+---+---.
| size | .>| data... |
|---+---+---+---| | | . |
|c=1| | | . . .
|---+---+---+---| | . . .
| direct ptr -----' . .
'---------------'
sign(size)=1, count>=2 => indirect:
.---+---+---+---. .---+---+---+---. .---+---+---+---.
| size | .>| size | .>| data... |
|---+---+---+---| | |---+---+---+---| | | . |
|c>1| | | |c=1| | | . . .
|---+---+---+---| | |---+---+---+---| | . . .
| indirect ptr ---' | direct ptr -----' . .
'---------------' '---------------' .---+---+---+---.
| size | .>| data... |
|---+---+---+---| | | . |
|c=1| | | . . .
|---+---+---+---| | . . .
| direct ptr -----' . .
'---+---+---+---'
| . |
| . |
. . .
. .
. .
note only one indirect layer is allowed due to no recursion
If the size field's sign bit=1, the lfsr_data_t points on-disk:
sign(size)=0 => on-disk:
.---+---+---+---. .....
| size | ..'' ''..
|---+---+---+---| : : :
| block ------+->| ..:|
|---+---+---+---| | |......( )::::::|
| off -------' |:::' : |
'---------------' :' : :
''.. :.''
'''''
My goal with this commit was to test the new implementation and see how
it would impact code/RAM size before adopting it in the actual file
handling code, and the results are... not great...
code stack
before: 24668 1840
after: 25552 (+3.5%) 1920 (+4.2%)
I think most of the new cost comes from the now correct handling of
read/cmp with concatentated datas, which previously would just assert.
This change gives us LFSR_DATA_CAT, so I will be working with it for
now, but this may be worth looking at again in the future. Maybe the
correct handling of read/cmp should just be reverted to an assert...
This commit is contained in:
@@ -432,19 +432,36 @@ typedef struct lfsr_data {
|
||||
// After removing the sign bit, the size always encodes the resulting
|
||||
// size on-disk.
|
||||
//
|
||||
// After this the count field indicates the in-device representation,
|
||||
// which has a few forms:
|
||||
// - count == 0 => data inlined in data struct
|
||||
// - count == 1 => direct pointer to data
|
||||
// - count >= 2 => indirect pointer to array of datas
|
||||
//
|
||||
// The indirect pointer can point to inlined/direct datas or even
|
||||
// on-disk datas, but not more indirect datas as that would require
|
||||
// recursion.
|
||||
//
|
||||
lfs_ssize_t size;
|
||||
struct {
|
||||
lfs_ssize_t size;
|
||||
// This leb128 field is a bit of a hack that allows a single leb128
|
||||
// to be injected into lfsr_bd_progdata. Outside of
|
||||
// lfsr_bd_progdata, this field is invalid!
|
||||
int32_t leb128;
|
||||
const uint8_t *buffer;
|
||||
} buffer;
|
||||
uint8_t count;
|
||||
uint8_t buf[5];
|
||||
} inlined;
|
||||
struct {
|
||||
lfs_ssize_t size;
|
||||
uint8_t count;
|
||||
const uint8_t *buffer;
|
||||
} direct;
|
||||
struct {
|
||||
lfs_ssize_t size;
|
||||
uint8_t count;
|
||||
const struct lfsr_data *datas;
|
||||
} indirect;
|
||||
struct {
|
||||
lfs_ssize_t size;
|
||||
lfs_size_t off;
|
||||
lfs_block_t block;
|
||||
lfs_size_t off;
|
||||
} disk;
|
||||
} u;
|
||||
} lfsr_data_t;
|
||||
|
||||
Reference in New Issue
Block a user