5. msgpack and janet
janet functions for msgpack will be loaded using
the funciton monolith_janet_msgpack
.
<<moncmp_functions>>=
<<moncmp_janet_functions>>
static const JanetReg cfuns[] = {
{"monolith/msgpack-read", j_msgpack_read,
"Reads a msgpack buffer loaded in Janet.",
},
{NULL, NULL, NULL}
};
void monolith_janet_msgpack(JanetTable *env)
{
janet_cfuns(env, NULL, cfuns);
}
A function that converts a valid msgpack stream
(encoded in a buffer) to a janet array. This function
will be called monolith/msgpack-read
.
<<moncmp_janet_functions>>=
typedef struct {
JanetBuffer *buf;
size_t pos;
} j_mp_d;
static bool read_bytes(void *data, size_t sz, j_mp_d *jmp)
{
size_t n;
uint8_t *bytes;
uint8_t *in;
bytes = data;
in = (uint8_t *)jmp->buf->data;
if (jmp->pos + sz > jmp->buf->count) {
/* fprintf(stderr, */
/* "Read %ld out of range of size %d\n", */
/* jmp->pos + sz, jmp->buf->count); */
return false;
}
for (n = 0; n < sz; n++) {
bytes[n] = in[jmp->pos + n];
}
jmp->pos += sz;
return true;
}
/* instead of copying, return pointer directly, then move
,* position. Used for things like strings.
,*/
static uint8_t * get_data(j_mp_d *jmp, size_t sz)
{
uint8_t *in;
size_t pos;
in = (uint8_t *)jmp->buf->data;
pos = jmp->pos;
jmp->pos += sz;
return &in[pos];
}
static bool j_mp_read(cmp_ctx_t *ctx, void *data, size_t limit)
{
return read_bytes(data, limit, (j_mp_d *)ctx->buf);
}
/* static void error_and_exit(const char *msg) */
/* { */
/* fprintf(stderr, "%s\n\n", msg); */
/* } */
static int append_object(cmp_ctx_t *cmp,
JanetArray *array,
j_mp_d *jmp)
{
cmp_object_t obj;
if (!cmp_read_object(cmp, &obj)) {
if (jmp->pos >= jmp->buf->count) return 0;
return 0;
}
switch (obj.type) {
case CMP_TYPE_POSITIVE_FIXNUM:
case CMP_TYPE_UINT8:
janet_array_push(array,
janet_wrap_integer(obj.as.u8));
break;
case CMP_TYPE_FIXMAP:
case CMP_TYPE_MAP16:
case CMP_TYPE_MAP32:
printf("Map: %u\n", obj.as.map_size);
break;
case CMP_TYPE_FIXARRAY:
case CMP_TYPE_ARRAY16:
case CMP_TYPE_ARRAY32: {
int n;
size_t cap;
JanetArray *a;
cap = obj.as.array_size;
a = janet_array(cap);
for (n = 0; n < cap; n++) {
append_object(cmp, a, jmp);
}
janet_array_push(array, janet_wrap_array(a));
break;
}
case CMP_TYPE_FIXSTR:
case CMP_TYPE_STR8:
case CMP_TYPE_STR16:
case CMP_TYPE_STR32: {
const uint8_t *str;
str = get_data(jmp, obj.as.str_size);
janet_array_push(array,
janet_wrap_string(
janet_string(str,
obj.as.str_size)));
break;
}
/* case CMP_TYPE_BIN8: */
/* case CMP_TYPE_BIN16: */
/* case CMP_TYPE_BIN32: */
/* memset(sbuf, 0, sizeof(sbuf)); */
/* if (!read_bytes(sbuf, obj.as.bin_size, jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* printf("Binary: %s\n", sbuf); */
/* break; */
case CMP_TYPE_NIL:
janet_array_push(array, janet_wrap_nil());
break;
case CMP_TYPE_BOOLEAN:
janet_array_push(array,
janet_wrap_boolean(obj.as.boolean));
break;
/* case CMP_TYPE_EXT8: */
/* case CMP_TYPE_EXT16: */
/* case CMP_TYPE_EXT32: */
/* case CMP_TYPE_FIXEXT1: */
/* case CMP_TYPE_FIXEXT2: */
/* case CMP_TYPE_FIXEXT4: */
/* case CMP_TYPE_FIXEXT8: */
/* case CMP_TYPE_FIXEXT16: */
/* if (obj.as.ext.type == 1) { /\* Date object *\/ */
/* if (!read_bytes(&year, sizeof(uint16_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* if (!read_bytes(&month, sizeof(uint8_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* if (!read_bytes(&day, sizeof(uint8_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* printf("Date: %u/%u/%u\n", year, month, day); */
/* } */
/* else { */
/* printf("Extended type {%d, %u}: ", */
/* obj.as.ext.type, obj.as.ext.size */
/* ); */
/* while (obj.as.ext.size--) { */
/* read_bytes(sbuf, sizeof(uint8_t), jmp); */
/* printf("%02x ", sbuf[0]); */
/* } */
/* printf("\n"); */
/* } */
/* break; */
case CMP_TYPE_FLOAT:
janet_array_push(array,
janet_wrap_number(obj.as.flt));
break;
case CMP_TYPE_DOUBLE:
janet_array_push(array,
janet_wrap_number(obj.as.dbl));
break;
case CMP_TYPE_UINT16:
janet_array_push(array,
janet_wrap_integer(obj.as.u16));
break;
case CMP_TYPE_UINT32:
janet_array_push(array,
janet_wrap_integer(obj.as.u32));
break;
case CMP_TYPE_UINT64:
janet_array_push(array,
janet_wrap_integer(obj.as.u64));
break;
case CMP_TYPE_NEGATIVE_FIXNUM:
case CMP_TYPE_SINT8:
janet_array_push(array,
janet_wrap_integer(obj.as.s8));
break;
case CMP_TYPE_SINT16:
janet_array_push(array,
janet_wrap_integer(obj.as.s16));
break;
case CMP_TYPE_SINT32:
janet_array_push(array,
janet_wrap_integer(obj.as.s32));
break;
case CMP_TYPE_SINT64:
janet_array_push(array,
janet_wrap_integer(obj.as.s64));
break;
default:
printf("Unrecognized object type %u\n", obj.type);
break;
}
return 1;
}
static void parse_data(cmp_ctx_t *cmp,
JanetArray *array,
j_mp_d *jmp)
{
/* uint16_t year = 1983; */
/* uint8_t month = 5; */
/* uint8_t day = 28; */
/* char sbuf[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; */
while (1) {
if (!append_object(cmp, array, jmp)) break;
/* cmp_object_t obj; */
/* if (!cmp_read_object(cmp, &obj)) { */
/* if (jmp->pos >= jmp->buf->count) break; */
/* error_and_exit(cmp_strerror(cmp)); */
/* break; */
/* } */
/* switch (obj.type) { */
/* case CMP_TYPE_POSITIVE_FIXNUM: */
/* case CMP_TYPE_UINT8: */
/* printf("Unsigned Integer: %u\n", obj.as.u8); */
/* break; */
/* case CMP_TYPE_FIXMAP: */
/* case CMP_TYPE_MAP16: */
/* case CMP_TYPE_MAP32: */
/* printf("Map: %u\n", obj.as.map_size); */
/* break; */
/* case CMP_TYPE_FIXARRAY: */
/* case CMP_TYPE_ARRAY16: */
/* case CMP_TYPE_ARRAY32: */
/* printf("Array: %u\n", obj.as.array_size); */
/* break; */
/* case CMP_TYPE_FIXSTR: */
/* case CMP_TYPE_STR8: */
/* case CMP_TYPE_STR16: */
/* case CMP_TYPE_STR32: { */
/* const uint8_t *str; */
/* str = get_data(jmp, obj.as.str_size); */
/* janet_array_push(array, */
/* janet_wrap_string( */
/* janet_string(str, */
/* obj.as.str_size))); */
/* break; */
/* } */
/* case CMP_TYPE_BIN8: */
/* case CMP_TYPE_BIN16: */
/* case CMP_TYPE_BIN32: */
/* memset(sbuf, 0, sizeof(sbuf)); */
/* if (!read_bytes(sbuf, obj.as.bin_size, jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* printf("Binary: %s\n", sbuf); */
/* break; */
/* case CMP_TYPE_NIL: */
/* janet_array_push(array, janet_wrap_nil()); */
/* break; */
/* case CMP_TYPE_BOOLEAN: */
/* janet_array_push(array, */
/* janet_wrap_boolean(obj.as.boolean)); */
/* case CMP_TYPE_EXT8: */
/* case CMP_TYPE_EXT16: */
/* case CMP_TYPE_EXT32: */
/* case CMP_TYPE_FIXEXT1: */
/* case CMP_TYPE_FIXEXT2: */
/* case CMP_TYPE_FIXEXT4: */
/* case CMP_TYPE_FIXEXT8: */
/* case CMP_TYPE_FIXEXT16: */
/* if (obj.as.ext.type == 1) { /\* Date object *\/ */
/* if (!read_bytes(&year, sizeof(uint16_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* if (!read_bytes(&month, sizeof(uint8_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* if (!read_bytes(&day, sizeof(uint8_t), jmp)) { */
/* error_and_exit(strerror(errno)); */
/* break; */
/* } */
/* printf("Date: %u/%u/%u\n", year, month, day); */
/* } */
/* else { */
/* printf("Extended type {%d, %u}: ", */
/* obj.as.ext.type, obj.as.ext.size */
/* ); */
/* while (obj.as.ext.size--) { */
/* read_bytes(sbuf, sizeof(uint8_t), jmp); */
/* printf("%02x ", sbuf[0]); */
/* } */
/* printf("\n"); */
/* } */
/* break; */
/* case CMP_TYPE_FLOAT: */
/* janet_array_push(array, */
/* janet_wrap_number(obj.as.flt)); */
/* break; */
/* case CMP_TYPE_DOUBLE: */
/* janet_array_push(array, */
/* janet_wrap_number(obj.as.dbl)); */
/* break; */
/* case CMP_TYPE_UINT16: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.u16)); */
/* break; */
/* case CMP_TYPE_UINT32: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.u32)); */
/* break; */
/* case CMP_TYPE_UINT64: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.u64)); */
/* break; */
/* case CMP_TYPE_NEGATIVE_FIXNUM: */
/* case CMP_TYPE_SINT8: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.s8)); */
/* break; */
/* case CMP_TYPE_SINT16: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.s16)); */
/* break; */
/* case CMP_TYPE_SINT32: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.s32)); */
/* break; */
/* case CMP_TYPE_SINT64: */
/* janet_array_push(array, */
/* janet_wrap_integer(obj.as.s64)); */
/* break; */
/* default: */
/* printf("Unrecognized object type %u\n", obj.type); */
/* break; */
/* } */
}
}
static Janet j_msgpack_read(int32_t argc, Janet *argv)
{
JanetArray *array;
JanetBuffer *buf;
cmp_ctx_t cmp;
j_mp_d data;
janet_fixarity(argc, 1);
buf = janet_getbuffer(argv, 0);
array = janet_array(16);
data.buf = buf;
data.pos = 0;
cmp_init(&cmp, &data, j_mp_read, NULL, NULL);
parse_data(&cmp, array, &data);
return janet_wrap_array(array);
}
CMP has the ability to read through a msgpack buffer
as a stream of objects via the function cmp_read_object
.
A giant case switch would then parse the type flag in the object and react accordingly. For janet, this means pushing decoding + pushing values onto an array that get returned.
prev | home | next