blob: 8cee485db06de8b7a5733f04179f85defdf46b43 [file] [log] [blame]
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "cn-cbor/cn-cbor.h"
#ifdef USE_CBOR_CONTEXT
#define CBOR_CONTEXT_PARAM , NULL
#else
#define CBOR_CONTEXT_PARAM
#endif
#define ERROR(msg, p) fprintf(stderr, "ERROR: " msg " %s\n", (p));
static unsigned char *load_file(const char *filepath, unsigned char **end)
{
struct stat st;
if (stat(filepath, &st) == -1) {
ERROR("can't find file", filepath);
return 0;
}
int fd = open(filepath, O_RDONLY);
if (fd == -1) {
ERROR("can't open file", filepath);
return 0;
}
unsigned char *text = malloc(st.st_size + 1); // this is not going to be freed
if (st.st_size != read(fd, text, st.st_size)) {
ERROR("can't read file", filepath);
close(fd);
return 0;
}
close(fd);
text[st.st_size] = '\0';
*end = text + st.st_size;
return text;
}
static void dump(const cn_cbor *cb, char *out, char **end, int indent)
{
if (!cb)
goto done;
int i;
cn_cbor *cp;
char finchar = ')'; /* most likely */
#define CPY(s, l) \
memcpy(out, s, l); \
out += l;
#define OUT(s) CPY(s, sizeof(s) - 1)
#define PRF(f, a) out += sprintf(out, f, a)
for (i = 0; i < indent; i++)
*out++ = ' ';
switch (cb->type) {
case CN_CBOR_TEXT_CHUNKED:
OUT("(_\n");
goto sequence;
case CN_CBOR_BYTES_CHUNKED:
OUT("(_\n\n");
goto sequence;
case CN_CBOR_TAG:
PRF("%ld(\n", cb->v.sint);
goto sequence;
case CN_CBOR_ARRAY:
finchar = ']';
OUT("[\n");
goto sequence;
case CN_CBOR_MAP:
finchar = '}';
OUT("{\n");
goto sequence;
sequence:
for (cp = cb->first_child; cp; cp = cp->next) {
dump(cp, out, &out, indent + 2);
}
for (i = 0; i < indent; i++)
*out++ = ' ';
*out++ = finchar;
break;
case CN_CBOR_BYTES:
OUT("h'");
for (i = 0; i < cb->length; i++)
PRF("%02x", cb->v.str[i] & 0xff);
*out++ = '\'';
break;
case CN_CBOR_TEXT:
*out++ = '"';
CPY(cb->v.str, cb->length); /* should escape stuff */
*out++ = '"';
break;
case CN_CBOR_NULL:
OUT("null");
break;
case CN_CBOR_TRUE:
OUT("true");
break;
case CN_CBOR_FALSE:
OUT("false");
break;
case CN_CBOR_UNDEF:
OUT("simple(23)");
break;
case CN_CBOR_INT:
PRF("%ld", cb->v.sint);
break;
case CN_CBOR_UINT:
PRF("%lu", cb->v.uint);
break;
case CN_CBOR_DOUBLE:
PRF("%e", cb->v.dbl);
break;
case CN_CBOR_SIMPLE:
PRF("simple(%ld)", cb->v.sint);
break;
default:
PRF("???%d???", cb->type);
break;
}
*out++ = '\n';
done:
*end = out;
}
const char *err_name[] = {
"CN_CBOR_NO_ERROR",
"CN_CBOR_ERR_OUT_OF_DATA",
"CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED",
"CN_CBOR_ERR_ODD_SIZE_INDEF_MAP",
"CN_CBOR_ERR_BREAK_OUTSIDE_INDEF",
"CN_CBOR_ERR_MT_UNDEF_FOR_INDEF",
"CN_CBOR_ERR_RESERVED_AI",
"CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING",
"CN_CBOR_ERR_OUT_OF_MEMORY",
"CN_CBOR_ERR_FLOAT_NOT_SUPPORTED",
};
static void cn_cbor_decode_test(const unsigned char *buf, int len)
{
struct cn_cbor_errback back;
const cn_cbor *ret = cn_cbor_decode(buf, len CBOR_CONTEXT_PARAM, &back);
if (ret)
printf("oops 1");
printf("%s at %d\n", err_name[back.err], back.pos);
}
int main(void)
{
char buf[100000];
unsigned char *end;
char *bufend;
unsigned char *s = load_file("cases.cbor", &end);
printf("%zd\n", end - s);
cn_cbor *cb = cn_cbor_decode(s, end - s CBOR_CONTEXT_PARAM, 0);
if (cb) {
dump(cb, buf, &bufend, 0);
*bufend = 0;
printf("%s\n", buf);
cn_cbor_free(cb CBOR_CONTEXT_PARAM);
cb = 0; /* for leaks testing */
}
cn_cbor_decode_test((const unsigned char *)"\xff", 1); /* break outside indef */
cn_cbor_decode_test((const unsigned char *)"\x1f", 1); /* mt undef for indef */
cn_cbor_decode_test((const unsigned char *)"\x00\x00", 2); /* not all data consumed */
cn_cbor_decode_test((const unsigned char *)"\x81", 1); /* out of data */
cn_cbor_decode_test((const unsigned char *)"\x1c", 1); /* reserved ai */
cn_cbor_decode_test((const unsigned char *)"\xbf\x00\xff", 3); /* odd size indef map */
cn_cbor_decode_test((const unsigned char *)"\x7f\x40\xff", 3); /* wrong nesting in indef string */
system("leaks test");
}
/* cn-cbor.c:112: CN_CBOR_FAIL("out of memory"); */