Skip to content

Instantly share code, notes, and snippets.

@adrianparvino
Last active August 31, 2019 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrianparvino/1d3f1fabb8262735aa8d3748bf8231b8 to your computer and use it in GitHub Desktop.
Save adrianparvino/1d3f1fabb8262735aa8d3748bf8231b8 to your computer and use it in GitHub Desktop.
#ifndef BUF_HANDLE_H
#define BUF_HANDLE_H
#include<stdlib.h>
#include<stdint.h>
struct buf_handle
{
uint8_t *tail;
ssize_t remaining;
uint16_t byte;
};
struct buf_handle *buf_handle_new(uint8_t *buf);
void buf_handle_close(struct buf_handle *handle);
void buf_handle_write(struct buf_handle *handle,
uint32_t x, ssize_t bits);
#endif
#include "buf_handle.h"
#include<stdlib.h>
#include<stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#include<string.h>
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
static inline uint16_t
movl(uint16_t x, uint8_t s)
{
return (x & 0xff00) | s;
}
static inline uint16_t
movu(uint16_t x, uint8_t s)
{
return (s << 8) | (x & 0xff);
}
static inline uint16_t
rot16l(uint16_t x, ssize_t s)
{
return x << s | x >> (16 - s);
}
static inline uint16_t
rot16r(uint16_t x, ssize_t s)
{
return x >> s | x << (16 - s);
}
static inline uint8_t
rot8r(uint8_t x, ssize_t s)
{
return x >> s | x << (8 - s);
}
struct buf_handle *
buf_handle_new(uint8_t *buf)
{
struct buf_handle *buf_handle = malloc(sizeof *buf_handle);
buf_handle->tail = buf;
buf_handle->remaining = 8;
buf_handle->byte = 0;
return buf_handle;
}
void
buf_handle_close(struct buf_handle *handle)
{
*handle->tail = handle->byte;
free(handle);
}
void
buf_handle_write(struct buf_handle *handle,
uint32_t x, ssize_t bits)
{
if (handle->remaining <= bits)
{
handle->byte = movl(handle->byte, x);
handle->byte = rot16r(handle->byte, handle->remaining);
x >>= handle->remaining;
bits -= handle->remaining;
*handle->tail++ = handle->byte >> 8;
handle->remaining = 8;
handle->byte = 0;
switch (bits/8)
{
case 3:
*handle->tail++ = x;
x >>= 8;
case 2:
*handle->tail++ = x;
x >>= 8;
case 1:
*handle->tail++ = x;
x >>= 8;
}
bits %= 8;
}
handle->byte = movl(handle->byte, x);
handle->byte = rot16r(handle->byte, bits);
handle->remaining -= bits;
}
typedef struct {
uint8_t *buf;
size_t offset;
uint8_t byte;
size_t bit;
} rwb;
void wbit(rwb *ctx, uint32_t x, int bits)
{
for (int i = 0; i < bits; i++) {
ctx->byte |= (x & 1) << ctx->bit++;
x >>= 1;
if (ctx->bit >= 8) {
ctx->buf[ctx->offset++] = ctx->byte;
ctx->byte = ctx->bit = 0;
}
}
}
void wflush(rwb *ctx)
{
ctx->buf[ctx->offset++] = ctx->byte;
ctx->byte = ctx->bit = 0;
}
int main(int argc, char *argv[argc])
{
const bool show_induvidual = true;
const int runs = 128 * 16;
uint64_t total = 0;
uint8_t *buf = malloc(256*4);
uint8_t *buf2 = malloc(256*4);
uint8_t *lengths = calloc(256, sizeof(int));
uint32_t *codes = calloc(256, sizeof(uint32_t));
rwb wctx = {
.buf = buf2,
.offset = 0,
.byte = 0,
.bit = 0,
};
for (int run = 0; run < runs; run++) {
srand(time(NULL));
for (int i = 0; i < 256; i++) {
lengths[i] = rand() % ((32 + 1) - 1) + 1;
}
int fd = open("/dev/urandom", O_RDONLY);
read(fd, codes, 256 * sizeof(uint32_t));
close(fd);
clock_t start = clock();
for (int j = 0; j < 1024; j++) {
wctx.offset = 0;
struct buf_handle *handle = buf_handle_new(buf);
for (int i = 0; i < 256; i++) {
buf_handle_write(handle, codes[i], lengths[i]);
// wbit(&wctx, codes[i], lengths[i]);
}
buf_handle_close(handle);
wflush(&wctx);
// assert(memcmp(buf, buf2, 32) == 0);
}
clock_t runtime = clock() - start;
if (show_induvidual)
printf("%lu\n", runtime);
total += runtime;
}
free(buf);
free(lengths);
free(codes);
printf("average: %f\n", (double)total / runs);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment