#include "frame.h"
#define READ_(bits,size) \
\
uint_fast##size##_t read##bits(frameItem* frame) { \
static_assert(bits <= size, "Return type too small to hold the requested number of bits."); \
uint_fast##size##_t result = 0; \
\
UWORD* frame_ptr = frame->edge - 1 - frame->offset / UWORD_BIT; \
\
size_t frame_shift = UWORD_BIT - (frame->offset % UWORD_BIT); \
size_t n = bits; \
if (frame_shift < n) { \
\
result |= (uint_fast##size##_t)((uint_fast##size##_t)LSBkeep(*frame_ptr, frame_shift) << (n - frame_shift)); \
frame->offset += frame_shift; \
n -= frame_shift; \
frame_shift = UWORD_BIT; \
frame_ptr--; \
while (UWORD_BIT < n) { \
\
result |= (uint_fast##size##_t)((uint_fast##size##_t)(*frame_ptr) << (n - UWORD_BIT)); \
frame->offset += UWORD_BIT; \
n -= UWORD_BIT; \
frame_ptr--; \
} \
} \
\
result |= (uint_fast##size##_t)(LSBkeep((UWORD)(*frame_ptr >> (frame_shift - n)), n)); \
frame->offset += n; \
return result; \
}
READ_(4,8)
READ_(8,8)
READ_(16,16)
READ_(32,32)
READ_(64,64)
#define WRITE_(bits) \
\
void write##bits(frameItem* frame, uint_fast##bits##_t x) { \
\
UWORD* frame_ptr = frame->edge + (frame->offset - 1) / UWORD_BIT; \
\
size_t frame_shift = (frame->offset - 1) % UWORD_BIT + 1; \
size_t n = bits; \
if (frame_shift < n) { \
\
*frame_ptr = LSBclear(*frame_ptr, frame_shift) | LSBkeep((UWORD)(x >> (n - frame_shift)), frame_shift); \
frame->offset -= frame_shift; \
n -= frame_shift; \
frame_shift = UWORD_BIT; \
frame_ptr--; \
while (UWORD_BIT < n) { \
\
*frame_ptr = (UWORD)(x >> (n - UWORD_BIT)); \
frame->offset -= UWORD_BIT; \
n -= UWORD_BIT; \
frame_ptr--; \
} \
} \
\
*frame_ptr = (UWORD)(LSBclear(*frame_ptr, frame_shift) | (LSBkeep((UWORD)x, n) << (frame_shift - n))); \
frame->offset -= n; \
}
WRITE_(8)
WRITE_(16)
WRITE_(32)
WRITE_(64)
void read_buffer8(unsigned char* buf, size_t* len, frameItem* src, int n) {
simplicity_debug_assert(0 <= n && n < 16);
*len = 0;
for (size_t i = (size_t)1 << n; 0 < i; i /= 2) {
if (readBit(src)) {
read8s(buf, i, src);
buf += i; *len += i;
} else {
forwardBits(src, i*8);
}
}
}
void write_buffer8(frameItem* dst, const unsigned char* buf, size_t len, int n) {
simplicity_debug_assert(0 <= n && n < 16);
simplicity_debug_assert(len < ((size_t)1<<(n+1)));
for (size_t i = (size_t)1 << n; 0 < i; i /= 2) {
if (writeBit(dst, i <= len)) {
write8s(dst, buf, i);
buf += i; len -= i;
} else {
skipBits(dst, i*8);
}
}
}
bool read_sha256_context(sha256_context* ctx, frameItem* src) {
size_t len;
uint_fast64_t compressionCount;
read_buffer8(ctx->block, &len, src, 5);
compressionCount = read64(src);
ctx->counter = ((compressionCount*1U) << 6) + len;
read32s(ctx->output, 8, src);
ctx->overflow = (sha256_max_counter >> 6) <= compressionCount;
return !ctx->overflow;
}
bool write_sha256_context(frameItem* dst, const sha256_context* ctx) {
write_buffer8(dst, ctx->block, ctx->counter % 64, 5);
write64(dst, ctx->counter >> 6);
write32s(dst, ctx->output, 8);
return !ctx->overflow;
}
static void copyBitsHelper(const frameItem* dst, const frameItem *src, size_t n) {
UWORD* src_ptr = src->edge - 1 - src->offset / UWORD_BIT;
UWORD* dst_ptr = dst->edge + (dst->offset - 1) / UWORD_BIT;
size_t src_shift = UWORD_BIT - (src->offset % UWORD_BIT);
size_t dst_shift = dst->offset % UWORD_BIT;
if (dst_shift) {
*dst_ptr = LSBclear(*dst_ptr, dst_shift);
if (src_shift < dst_shift) {
*dst_ptr |= (UWORD)(LSBkeep(*src_ptr, src_shift) << (dst_shift - src_shift));
if (n <= src_shift) return;
n -= src_shift;
dst_shift -= src_shift;
src_ptr--;
src_shift = UWORD_BIT;
}
*dst_ptr |= LSBkeep((UWORD)(*src_ptr >> (src_shift - dst_shift)), dst_shift);
if (n <= dst_shift) return;
n -= dst_shift;
src_shift -= dst_shift;
dst_ptr--;
}
if (0 == src_shift % UWORD_BIT) {
size_t m = ROUND_UWORD(n);
memcpy(dst_ptr - (m - 1), src_ptr - (m - src_shift / UWORD_BIT), m * sizeof(UWORD));
} else {
while(1) {
*dst_ptr = (UWORD)(LSBkeep(*src_ptr, src_shift) << (UWORD_BIT - src_shift));
if (n <= src_shift) return;
*dst_ptr |= (UWORD)(*(src_ptr - 1) >> src_shift);
if (n <= UWORD_BIT) return;
n -= UWORD_BIT;
dst_ptr--; src_ptr--;
}
}
}
void copyBits(frameItem* dst, const frameItem* src, size_t n) {
if (0 == n) return;
copyBitsHelper(dst, src, n);
dst->offset -= n;
}