Files
scoutfs/utils/src/srch.c
Zach Brown 9491c784e7 Add srch_encode_entry() for userspace utils
Signed-off-by: Zach Brown <zab@versity.com>
2025-01-22 09:57:56 -08:00

81 lines
1.7 KiB
C

#include <errno.h>
#include "sparse.h"
#include "util.h"
#include "format.h"
#include "srch.h"
/* shifting by width is undefined :/ */
#define BYTE_MASK(b) ((1ULL << (b << 3)) - 1)
static u64 byte_masks[] = {
0, BYTE_MASK(1), BYTE_MASK(2), BYTE_MASK(3),
BYTE_MASK(4), BYTE_MASK(5), BYTE_MASK(6), BYTE_MASK(7), U64_MAX,
};
static u64 decode_u64(void *buf, int bytes)
{
u64 val = get_unaligned_le64(buf) & byte_masks[bytes];
return (val >> 1) ^ (-(val & 1));
}
int srch_decode_entry(void *buf, struct scoutfs_srch_entry *sre,
struct scoutfs_srch_entry *prev)
{
u64 diffs[3];
u16 lengths;
int bytes;
int tot;
int i;
lengths = get_unaligned_le16(buf);
tot = 2;
for (i = 0; i < array_size(diffs); i++) {
bytes = min(8, lengths & 15);
diffs[i] = decode_u64(buf + tot, bytes);
tot += bytes;
lengths >>= 4;
}
sre->hash = cpu_to_le64(le64_to_cpu(prev->hash) + diffs[0]);
sre->ino = cpu_to_le64(le64_to_cpu(prev->ino) + diffs[1]);
sre->id = cpu_to_le64(le64_to_cpu(prev->id) + diffs[2]);
return tot;
}
static int encode_u64(__le64 *buf, u64 val)
{
int bytes;
val = (val << 1) ^ ((s64)val >> 63); /* shift sign extend */
bytes = (fls64(val) + 7) >> 3;
put_unaligned_le64(val, buf);
return bytes;
}
int srch_encode_entry(void *buf, struct scoutfs_srch_entry *sre, struct scoutfs_srch_entry *prev)
{
u64 diffs[] = {
le64_to_cpu(sre->hash) - le64_to_cpu(prev->hash),
le64_to_cpu(sre->ino) - le64_to_cpu(prev->ino),
le64_to_cpu(sre->id) - le64_to_cpu(prev->id),
};
u16 lengths = 0;
int bytes;
int tot = 2;
int i;
for (i = 0; i < array_size(diffs); i++) {
bytes = encode_u64(buf + tot, diffs[i]);
lengths |= bytes << (i << 2);
tot += bytes;
}
put_unaligned_le16(lengths, buf);
return tot;
}