mischiefinitial commitbd439e57 years agoHistory
286 lines · 3.9 KB · C
RawDownload
#include <u.h>#include <libc.h> #include "cbor.h"#include "cborimpl.h" typedef ulong (*encfun)(cbor_coder *d, cbor *c, int justsize); static ulong cbor_enc(cbor_coder *d, cbor *c, int justsize); static ulongenc_size(cbor_coder *d, u64int v, uchar major, int justsize){	ulong n;	uchar *p; 	if(v < 24){		n = 1;		major |= v;	} else if(v < 0x100ULL){		n = 2;		major |= 24;	} else if(v < 0x10000ULL){		n = 3;		major |= 25;	} else if(v < 0x100000000ULL){		n = 5;		major |= 26;	} else {		n = 9;		major |= 27;	} 	if(justsize)		return n; 	p = cbor_take(d, n);	if(p == nil)		return 0; 	*p++ = major; 	switch(n){	default:		abort();	case 9:		*p++ = v >> 56;		*p++ = v >> 48;		*p++ = v >> 40;		*p++ = v >> 32;	case 5:		*p++ = v >> 24;		*p++ = v >> 16;	case 3:		*p++ = v >> 8;	case 2:		*p = v;	case 1:		;	} 	return n;} static ulongenc_u(cbor_coder *d, cbor *c, int justsize){	return enc_size(d, c->uint, 0<<5, justsize);} static ulongenc_s(cbor_coder *d, cbor *c, int justsize){	return enc_size(d, ~c->sint, 1<<5, justsize);} static ulongenc_data_common(cbor_coder *d, cbor *c, uchar major, int justsize){	ulong rv;	uchar *p; 	rv = enc_size(d, c->len, major, justsize);	if(rv == 0)		return 0; 	if(justsize)		return rv + c->len; 	p = cbor_take(d, c->len);	memmove(p, c->byte, c->len); 	return rv + c->len;} static ulongenc_byte(cbor_coder *d, cbor *c, int justsize){	return enc_data_common(d, c, 2<<5, justsize);} static ulongenc_string(cbor_coder *d, cbor *c, int justsize){	return enc_data_common(d, c, 3<<5, justsize);} static ulongenc_array_common(cbor_coder *d, cbor *c, uchar major, int justsize){ 	int i;	ulong rv, r; 	rv = enc_size(d, c->len, major, justsize);	if(rv == 0)		return 0; 	for(i = 0; i < c->len; i++){		r = cbor_enc(d, c->array[i], justsize);		if(r == 0)			return 0;		rv += r;	} 	return rv;} static ulongenc_a(cbor_coder *d, cbor *c, int justsize){	return enc_array_common(d, c, 4<<5, justsize);} static ulongenc_m(cbor_coder *d, cbor *c, int justsize){	return enc_array_common(d, c, 5<<5, justsize);} static ulongenc_m_e(cbor_coder *d, cbor *c, int justsize){	ulong k, v; 	k = cbor_enc(d, c->key, justsize);	if(k == 0)		return 0; 	v = cbor_enc(d, c->value, justsize);	if(v == 0)		return 0; 	return k + v;} static ulongenc_t(cbor_coder *d, cbor *c, int justsize){	ulong t, e; 	t = enc_size(d, c->tag, 6<<5, justsize);	if(t == 0)		return 0; 	e = cbor_enc(d, c->item, justsize);	if(t == 0)		return 0; 	return t + e;} static ulongenc_null(cbor_coder *d, cbor *c, int justsize){	uchar *p; 	if(justsize)		return 1; 	p = cbor_take(d, 1);	if(p == nil)		return 0; 	*p = 0xf6; 	return 1;} static ulongenc_f(cbor_coder *d, cbor *c, int justsize){	u32int v;	uchar *p; 	if(justsize)		return 5; 	p = cbor_take(d, 5);	if(p == nil)		return 0; 	*p++ = 0xfa; 	memcpy(&v, &c->f, 4);	*p++ = v >> 24;	*p++ = v >> 16;	*p++ = v >> 8;	*p = v; 	return 5;} static ulongenc_d(cbor_coder *d, cbor *c, int justsize){	u64int v;	uchar *p; 	if(justsize)		return 9; 	p = cbor_take(d, 9);	if(p == nil)		return 0; 	*p++ = 0xfb; 	memcpy(&v, &c->f, 8);	*p++ = v >> 56;	*p++ = v >> 48;	*p++ = v >> 40;	*p++ = v >> 32;	*p++ = v >> 24;	*p++ = v >> 16;	*p++ = v >> 8;	*p = v; 	return 9;} static encfun encfuns[] = {[CBOR_UINT]			enc_u,[CBOR_SINT]			enc_s,[CBOR_BYTE]			enc_byte,[CBOR_STRING]		enc_string,[CBOR_ARRAY]		enc_a,[CBOR_MAP]			enc_m,[CBOR_MAP_ELEMENT]	enc_m_e,[CBOR_TAG]			enc_t,[CBOR_NULL]			enc_null,[CBOR_FLOAT]		enc_f,[CBOR_DOUBLE]		enc_d,}; static ulongcbor_enc(cbor_coder *d, cbor *c, int justsize){	encfun f; 	assert(c->type < CBOR_TYPE_MAX); 	f = encfuns[c->type];	assert(f != nil); 	return f(d, c, justsize);} ulongcbor_encode(cbor *c, unsigned char *buf, ulong n){	cbor_coder d = {		.alloc = nil,		.s = buf,		.p = buf,		.e = buf + n,	}; 	return cbor_enc(&d, c, 0);} ulongcbor_encode_size(cbor *c){	return cbor_enc(nil, c, 1);}