Introduce bincode.h and scaffold.h. The former is for bincode-specific reading from a data bufer, the latter is for common reusable components (scaffolding) across the project
Y26WT3ZFN7KSVXOZ26B5Y2OR4M4VQYQLPMAHPC4O5VIT3ENBISXAC
WMFNGOYTKIZ7L25V3KMJPSWK23DTN6G3ESP6M55YIH6UTHFKL2XAC
PEUS54XQ5KJQYAVUYBG5MWLEHIOVPMZ3ANVC7HPQP6JUWWPRDW5AC
VKLGQREYOZDV46F672RFE5XJO3OEOP4EHTCWZYOJY24HVPQX3L6QC
Q7TKZCJP2Z75EICZYKCEZDHKGERSOKZGMTSU3UXETBHTF663T66AC
RIWSVVASWLJQQTSVRHIIUPENOZWOMHQLZMTQVGJUS2ZUGDPSWWIQC
OBKF6SIIFFHHY7YWKPPX75N23NAVUD5662DKIHXSSIDPKKXQ5ZDQC
X36ICMJNYKJF35ZUEVCCR33JOZPCPZQ6KSGEQI3RZND2P5EDASLQC
B3XLVPNC4COLLC3FUE34Y7HIKTMF6CJZUASZOU3YM2YGPZKJZP7QC
3OHR6ZPHN53SVWJL4GUKKUC223IPXA73UPBFJCM4ENGS27AKHN6AC
#ifndef SCAFFOLD_H
#define SCAFFOLD_H
/* Various scaffolding functions around stdlib functions */
void *xmalloc(size_t size);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "scaffold.h"
/**
* Expand to support varargs like a regular printf
*/
void die(const char *msg)
{
fprintf(stderr, msg);
exit(57);
}
void *
xmalloc(size_t size)
{
void *ret;
ret = malloc(size);
if (!ret)
die("Unable to allocate memory");
return ret;
}
/* TODO Decode into 'struct hashed' */
p = buf;
dump_buf("hashed", p, hashed_len);
hashed.version = bincode_getu64(p);
printf("version = %lu\n", hashed.version);
p += sizeof(uint64_t);
len = bincode_getu64(p);
p += sizeof(uint64_t);
hashed.header.message = bincode_getstr(p, len);
p += len;
printf("message = '%s'\n", hashed.header.message);
/**
* Description! This is like the commit "body", and is optional, so we
* have a byte indicating its presence, '0' = None, '1' =
* Some(description)
*/
if (*p++) {
len = bincode_getu64(p);
p += sizeof(uint64_t);
hashed.header.description = bincode_getstr(p, len);
p += len;
printf("description = '%s'\n", hashed.header.description);
} else
printf("description = (none)\n");
len = bincode_getu64(p);
p += sizeof(uint64_t);
#ifndef BINCODE_H
#define BINCODE_H
/** Requires: <stdint.h> */
/**
* Definitions for the bincode encode/decode routines.
*
* Generally, the idea here is that you open a file, get a file descriptor and
* use the encode/decode routines to get components read from the fd and and
* decoded as the type you want.
*/
/**
* Some notes regarding the bincode format:
*
* Enum types: The order of the variants matter, as the encoding indicates the
* variant with a u32.
*/
uint16_t bincode_getu16(uint8_t *);
uint32_t bincode_getu32(uint8_t *);
uint64_t bincode_getu64(uint8_t *);
/**
* Allocate and return a string of the given length.
*
* The memory allocated shall be the given length plus one, to hold the
* terminating zero.
*
* Returns the allocated string. The caller is responsible for deallocating.
*/
char *bincode_getstr(uint8_t *, size_t);
/* void bincode_putu16(uint8_t *, uint16_t); */
/* void bincode_putu32(uint8_t *, uint32_t); */
/* void bincode_putu64(uint8_t *, uint64_t); */
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "scaffold.h"
#include "bincode.h"
uint16_t
bincode_getu16(uint8_t *b)
{
return (uint16_t)b[1] << 8 | (uint16_t)b[0];
}
uint32_t
bincode_getu32(uint8_t *b)
{
return (uint32_t)b[3] << 24
| (uint32_t)b[2] << 16
| (uint32_t)b[1] << 8
| (uint32_t)b[0];
}
uint64_t
bincode_getu64(uint8_t *b)
{
return (uint64_t)b[7] << 56
| (uint64_t)b[6] << 48
| (uint64_t)b[5] << 40
| (uint64_t)b[4] << 32
| (uint64_t)b[3] << 24
| (uint64_t)b[2] << 16
| (uint64_t)b[1] << 8
| (uint64_t)b[0];
}
char *
bincode_getstr(uint8_t *b, size_t len)
{
char *str;
str = xmalloc(len + 1);
memcpy(str, b, len);
str[len] = '\0';
return str;
}