#include <u.h>#include <libc.h>#include <bin.h> #include "cbor.h" static void*cbor_alloc_bin(void *context, ulong size){ return binalloc((Bin**)context, size, 0);} static void*cbor_realloc_bin(void *context, void *optr, ulong osize, ulong size){ return bingrow((Bin**)context, optr, osize, size, 0);} static voidcbor_free_bin(void *context, void *ptr){ USED(context); USED(ptr); return;} static char*cbor_print(cbor *c, char *bp, char *be){ int i; char *p, *e, *bracket; switch(c->type){ case CBOR_UINT: return seprint(bp, be, "%llud", c->uint); case CBOR_SINT: return seprint(bp, be, "%lld", c->sint); case CBOR_BYTE: return seprint(bp, be, "%.*H", c->len, c->byte); case CBOR_STRING: return seprint(bp, be, "\"%.*s\"", c->len, c->string); case CBOR_ARRAY: bracket = "[]"; goto arr; case CBOR_MAP: bracket = "{}"; arr: p = bp; e = be; p = seprint(p, e, "%c", bracket[0]); for(i = 0; i < c->len; i++){ p = cbor_print(c->array[i], p, e); if(c->len > 1 && i < c->len - 1) p = seprint(p, e, ", "); } p = seprint(p, e, "%c", bracket[1]); return p; case CBOR_MAP_ELEMENT: p = bp; e = be; p = cbor_print(c->key, p, e); p = seprint(p, e, ": "); p = cbor_print(c->value, p, e); return p; case CBOR_TAG: p = bp; e = be; p = seprint(p, e, "%llud(", c->tag); p = cbor_print(c->item, p, e); p = seprint(p, e, ")"); return p; case CBOR_NULL: return seprint(bp, be, "null"); case CBOR_FLOAT: return seprint(bp, be, "%#g", c->f); case CBOR_DOUBLE: return seprint(bp, be, "%#g", c->d); default: abort(); } return nil;} voidcbor_fprint(int fd, cbor *c){ char buf[2048]; cbor_print(c, buf, buf+sizeof(buf)); fprint(2, "%s\n", buf);} static char *tests[] = { "0x00", "0x01", "0x0a", "0x17", "0x1818", "0x1819", "0x1864", "0x1903e8", "0x1a000f4240", "0x1b000000e8d4a51000", "0x1bffffffffffffffff", //"0xc249010000000000000000", "0x3b0633275e3af7fffd", "0x3bffffffffffffffff", //"0xc349010000000000000000", "0x20", "0x29", "0x3863", "0x3903e7", /* single precision float */ "0xfa47c35000", "0xfa7f7fffff", "0xfa7f800000", "0xfa7fc00000", "0xfaff800000", /* double precision float */ "0xfb3ff199999999999a", "0xfb7e37e43c8800759c", "0xfbc010666666666666", "0xfb7ff0000000000000", "0xfb7ff8000000000000", "0xfbfff0000000000000", /* byte literal */ "0x4401020304", /* byte 1 */ "5818736c696768746c79206c6f6e676572207468616e20323421", /* byte 2 */ //"590018736c696768746c79206c6f6e676572207468616e20323421", /* byte 4 */ //"0x5a00000018736c696768746c79206c6f6e676572207468616e20323421", /* byte 8 */ //"0x5b000000000000000401020304", /* string literal */ "0x6449455446", /* string 1 */ "7818736c696768746c79206c6f6e676572207468616e20323421", /* string 2 */ //"0x79000449455446", /* string 4 */ //"0x7a0000000449455446", /* string 8 */ //"0x7b000000000000000449455446", /* array literal */ "0x83010203", /* nested array literal */ "0x8301820203820405", /* array 1 */ "0x9818010203040506070801020304050607080102030405060708", /* array 2 */ //"0x990003010203", /* array 4 */ //"0x9a00000003010203", /* array 8 */ //"0x9b0000000000000003010203", /* map literal */ "0xa201020304", /* map 1 */ //"0xb81801020304", /* map 2 */ //"0xb9000201020304", /* map 4 */ //"0xba0000000201020304", /* map 8 */ //"0xbb000000000000000201020304", /* map literal with nested array literal */ "0xa26161016162820203", /* various tags */ "0xc074323031332d30332d32315432303a30343a30305a", "0xc11a514b67b0", "0xc1fb41d452d9ec200000", "0xd74401020304", "0xd818456449455446", "0xd82076687474703a2f2f7777772e6578616d706c652e636f6d",}; static voidtest_decenc(void){ int j, i, n, np, rv; ulong sz, ne; char *p, pr[512]; uchar buf[512]; Bin *bin; cbor *c; cbor_allocator cbor_bin_allocator = { .alloc = cbor_alloc_bin, .realloc = cbor_realloc_bin, .free = cbor_free_bin, .context = &bin, }; for(j = 0; j < 1; j++) for(i = 0; i < nelem(tests); i++){ p = tests[i]; if(strncmp(p, "0x", 2) == 0) p += 2; n = strlen(p); fprint(2, "test %d: %d %s\n", i, n, p); rv = dec16(buf, sizeof(buf), p, n); assert(rv != -1); c = cbor_decode(&cbor_bin_allocator, buf, rv); if(c == nil) sysfatal("cbor_decode: %r"); cbor_fprint(2, c); //fprint(1, "%-032s %-032s\n", pr, tests[i]); sz = cbor_encode_size(c); ne = cbor_encode(c, buf, sz); if(ne != sz) fprint(2, "expected size: %lud: got: %lud\n", sz, ne); assert(ne == sz); np = snprint(pr, sizeof(pr), "%.*lH", (int)ne, buf); if(strncmp(pr, p, n) != 0){ fprint(2, "error: %02d %s\n", np, pr); sysfatal("test %d unexpected encoding", i); } } binfree(&bin); //sleep(100000);} static voidtest_encoder(void){ ulong n; uchar buf[512]; cbor c; c.type = CBOR_UINT; c.uint = 1000000000000ULL; n = cbor_encode(&c, buf, sizeof(buf)); fprint(2, "%ld 0x%.*lH\n", n, (int)n, buf);} static voidtest_array(void){ char pr[512]; cbor *a, *u; a = cbor_make_array(&cbor_default_allocator, 0); u = cbor_make_uint(&cbor_default_allocator, 42); a = cbor_array_append(&cbor_default_allocator, a, u); cbor_print(a, pr, pr+sizeof(pr)); fprint(2, "append: %s\n", pr); cbor_free(&cbor_default_allocator, a);} static voidtest_pack(void){ int rv, glen; char pr[512], *greet; u64int u; cbor *c; //c = cbor_pack(&cbor_default_allocator, "d", 42.0); c = cbor_pack(&cbor_default_allocator, "{sfsuss}", 2, "pi",3.14,6,"answer",42,8,"greeting",5,"hello"); assert(c != nil); cbor_print(c, pr, pr+sizeof(pr)); fprint(2, "pack: %s\n", pr); rv = cbor_unpack(&cbor_default_allocator, c, "{Ss}", "greeting", &glen, &greet); assert(rv == 0); fprint(2, "greet=%s\n", greet); cbor_default_allocator.free(cbor_default_allocator.context, greet); //assert(u == 42ULL); cbor_free(&cbor_default_allocator, c);} static voidusage(void){ fprint(2, "usage: %s\n", argv0); exits("usage");} voidmain(int argc, char *argv[]){ ARGBEGIN{ default: usage(); }ARGEND fmtinstall('H', encodefmt); test_decenc(); test_array(); test_pack(); exits(nil);}
#include <u.h>
#include <libc.h>
#include <bin.h>
#include "cbor.h"
static void*
cbor_alloc_bin(void *context, ulong size)
{
return binalloc((Bin**)context, size, 0);
}
static void*
cbor_realloc_bin(void *context, void *optr, ulong osize, ulong size)
{
return bingrow((Bin**)context, optr, osize, size, 0);
}
static void
cbor_free_bin(void *context, void *ptr)
{
USED(context);
USED(ptr);
return;
}
static char*
cbor_print(cbor *c, char *bp, char *be)
{
int i;
char *p, *e, *bracket;
switch(c->type){
case CBOR_UINT:
return seprint(bp, be, "%llud", c->uint);
case CBOR_SINT:
return seprint(bp, be, "%lld", c->sint);
case CBOR_BYTE:
return seprint(bp, be, "%.*H", c->len, c->byte);
case CBOR_STRING:
return seprint(bp, be, "\"%.*s\"", c->len, c->string);
case CBOR_ARRAY:
bracket = "[]";
goto arr;
case CBOR_MAP:
bracket = "{}";
arr:
p = bp;
e = be;
p = seprint(p, e, "%c", bracket[0]);
for(i = 0; i < c->len; i++){
p = cbor_print(c->array[i], p, e);
if(c->len > 1 && i < c->len - 1)
p = seprint(p, e, ", ");
}
p = seprint(p, e, "%c", bracket[1]);
return p;
case CBOR_MAP_ELEMENT:
p = bp;
e = be;
p = cbor_print(c->key, p, e);
p = seprint(p, e, ": ");
p = cbor_print(c->value, p, e);
return p;
case CBOR_TAG:
p = bp;
e = be;
p = seprint(p, e, "%llud(", c->tag);
p = cbor_print(c->item, p, e);
p = seprint(p, e, ")");
return p;
case CBOR_NULL:
return seprint(bp, be, "null");
case CBOR_FLOAT:
return seprint(bp, be, "%#g", c->f);
case CBOR_DOUBLE:
return seprint(bp, be, "%#g", c->d);
default:
abort();
}
return nil;
}
void
cbor_fprint(int fd, cbor *c)
{
char buf[2048];
cbor_print(c, buf, buf+sizeof(buf));
fprint(2, "%s\n", buf);
}
static char *tests[] = {
"0x00",
"0x01",
"0x0a",
"0x17",
"0x1818",
"0x1819",
"0x1864",
"0x1903e8",
"0x1a000f4240",
"0x1b000000e8d4a51000",
"0x1bffffffffffffffff",
//"0xc249010000000000000000",
"0x3b0633275e3af7fffd",
"0x3bffffffffffffffff",
//"0xc349010000000000000000",
"0x20",
"0x29",
"0x3863",
"0x3903e7",
/* single precision float */
"0xfa47c35000",
"0xfa7f7fffff",
"0xfa7f800000",
"0xfa7fc00000",
"0xfaff800000",
/* double precision float */
"0xfb3ff199999999999a",
"0xfb7e37e43c8800759c",
"0xfbc010666666666666",
"0xfb7ff0000000000000",
"0xfb7ff8000000000000",
"0xfbfff0000000000000",
/* byte literal */
"0x4401020304",
/* byte 1 */
"5818736c696768746c79206c6f6e676572207468616e20323421",
/* byte 2 */
//"590018736c696768746c79206c6f6e676572207468616e20323421",
/* byte 4 */
//"0x5a00000018736c696768746c79206c6f6e676572207468616e20323421",
/* byte 8 */
//"0x5b000000000000000401020304",
/* string literal */
"0x6449455446",
/* string 1 */
"7818736c696768746c79206c6f6e676572207468616e20323421",
/* string 2 */
//"0x79000449455446",
/* string 4 */
//"0x7a0000000449455446",
/* string 8 */
//"0x7b000000000000000449455446",
/* array literal */
"0x83010203",
/* nested array literal */
"0x8301820203820405",
/* array 1 */
"0x9818010203040506070801020304050607080102030405060708",
/* array 2 */
//"0x990003010203",
/* array 4 */
//"0x9a00000003010203",
/* array 8 */
//"0x9b0000000000000003010203",
/* map literal */
"0xa201020304",
/* map 1 */
//"0xb81801020304",
/* map 2 */
//"0xb9000201020304",
/* map 4 */
//"0xba0000000201020304",
/* map 8 */
//"0xbb000000000000000201020304",
/* map literal with nested array literal */
"0xa26161016162820203",
/* various tags */
"0xc074323031332d30332d32315432303a30343a30305a",
"0xc11a514b67b0",
"0xc1fb41d452d9ec200000",
"0xd74401020304",
"0xd818456449455446",
"0xd82076687474703a2f2f7777772e6578616d706c652e636f6d",
};
static void
test_decenc(void)
{
int j, i, n, np, rv;
ulong sz, ne;
char *p, pr[512];
uchar buf[512];
Bin *bin;
cbor *c;
cbor_allocator cbor_bin_allocator = {
.alloc = cbor_alloc_bin,
.realloc = cbor_realloc_bin,
.free = cbor_free_bin,
.context = &bin,
};
for(j = 0; j < 1; j++)
for(i = 0; i < nelem(tests); i++){
p = tests[i];
if(strncmp(p, "0x", 2) == 0)
p += 2;
n = strlen(p);
fprint(2, "test %d: %d %s\n", i, n, p);
rv = dec16(buf, sizeof(buf), p, n);
assert(rv != -1);
c = cbor_decode(&cbor_bin_allocator, buf, rv);
if(c == nil)
sysfatal("cbor_decode: %r");
cbor_fprint(2, c);
//fprint(1, "%-032s %-032s\n", pr, tests[i]);
sz = cbor_encode_size(c);
ne = cbor_encode(c, buf, sz);
if(ne != sz)
fprint(2, "expected size: %lud: got: %lud\n", sz, ne);
assert(ne == sz);
np = snprint(pr, sizeof(pr), "%.*lH", (int)ne, buf);
if(strncmp(pr, p, n) != 0){
fprint(2, "error: %02d %s\n", np, pr);
sysfatal("test %d unexpected encoding", i);
}
}
binfree(&bin);
//sleep(100000);
}
static void
test_encoder(void)
{
ulong n;
uchar buf[512];
cbor c;
c.type = CBOR_UINT;
c.uint = 1000000000000ULL;
n = cbor_encode(&c, buf, sizeof(buf));
fprint(2, "%ld 0x%.*lH\n", n, (int)n, buf);
}
static void
test_array(void)
{
char pr[512];
cbor *a, *u;
a = cbor_make_array(&cbor_default_allocator, 0);
u = cbor_make_uint(&cbor_default_allocator, 42);
a = cbor_array_append(&cbor_default_allocator, a, u);
cbor_print(a, pr, pr+sizeof(pr));
fprint(2, "append: %s\n", pr);
cbor_free(&cbor_default_allocator, a);
}
static void
test_pack(void)
{
int rv, glen;
char pr[512], *greet;
u64int u;
cbor *c;
//c = cbor_pack(&cbor_default_allocator, "d", 42.0);
c = cbor_pack(&cbor_default_allocator, "{sfsuss}", 2, "pi",3.14,6,"answer",42,8,"greeting",5,"hello");
assert(c != nil);
cbor_print(c, pr, pr+sizeof(pr));
fprint(2, "pack: %s\n", pr);
rv = cbor_unpack(&cbor_default_allocator, c, "{Ss}", "greeting", &glen, &greet);
assert(rv == 0);
fprint(2, "greet=%s\n", greet);
cbor_default_allocator.free(cbor_default_allocator.context, greet);
//assert(u == 42ULL);
cbor_free(&cbor_default_allocator, c);
}
static void
usage(void)
{
fprint(2, "usage: %s\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
ARGBEGIN{
default:
usage();
}ARGEND
fmtinstall('H', encodefmt);
test_decenc();
test_array();
test_pack();
exits(nil);
}