1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <string.h> 7 8 #include "cn-cbor/cn-cbor.h" 9 10 #ifdef USE_CBOR_CONTEXT 11 #define CBOR_CONTEXT_PARAM , NULL 12 #else 13 #define CBOR_CONTEXT_PARAM 14 #endif 15 16 #define ERROR(msg, p) fprintf(stderr, "ERROR: " msg " %s\n", (p)); 17 18 static unsigned char* load_file(const char* filepath, unsigned char **end) { 19 struct stat st; 20 if (stat(filepath, &st)==-1) { 21 ERROR("can't find file", filepath); 22 return 0; 23 } 24 int fd=open(filepath, O_RDONLY); 25 if (fd==-1) { 26 ERROR("can't open file", filepath); 27 return 0; 28 } 29 unsigned char* text=malloc(st.st_size+1); // this is not going to be freed 30 if (st.st_size!=read(fd, text, st.st_size)) { 31 ERROR("can't read file", filepath); 32 close(fd); 33 return 0; 34 } 35 close(fd); 36 text[st.st_size]='\0'; 37 *end = text + st.st_size; 38 return text; 39 } 40 41 static void dump(const cn_cbor* cb, char* out, char** end, int indent) { 42 if (!cb) 43 goto done; 44 int i; 45 cn_cbor* cp; 46 char finchar = ')'; /* most likely */ 47 48 #define CPY(s, l) memcpy(out, s, l); out += l; 49 #define OUT(s) CPY(s, sizeof(s)-1) 50 #define PRF(f, a) out += sprintf(out, f, a) 51 52 for (i = 0; i < indent; i++) *out++ = ' '; 53 switch (cb->type) { 54 case CN_CBOR_TEXT_CHUNKED: OUT("(_\n"); goto sequence; 55 case CN_CBOR_BYTES_CHUNKED: OUT("(_\n\n"); goto sequence; 56 case CN_CBOR_TAG: PRF("%ld(\n", cb->v.sint); goto sequence; 57 case CN_CBOR_ARRAY: finchar = ']'; OUT("[\n"); goto sequence; 58 case CN_CBOR_MAP: finchar = '}'; OUT("{\n"); goto sequence; 59 sequence: 60 for (cp = cb->first_child; cp; cp = cp->next) { 61 dump(cp, out, &out, indent+2); 62 } 63 for (i=0; i<indent; i++) *out++ = ' '; 64 *out++ = finchar; 65 break; 66 case CN_CBOR_BYTES: OUT("h'"); 67 for (i=0; i<cb->length; i++) 68 PRF("%02x", cb->v.str[i] & 0xff); 69 *out++ = '\''; 70 break; 71 case CN_CBOR_TEXT: *out++ = '"'; 72 CPY(cb->v.str, cb->length); /* should escape stuff */ 73 *out++ = '"'; 74 break; 75 case CN_CBOR_NULL: OUT("null"); break; 76 case CN_CBOR_TRUE: OUT("true"); break; 77 case CN_CBOR_FALSE: OUT("false"); break; 78 case CN_CBOR_UNDEF: OUT("simple(23)"); break; 79 case CN_CBOR_INT: PRF("%ld", cb->v.sint); break; 80 case CN_CBOR_UINT: PRF("%lu", cb->v.uint); break; 81 case CN_CBOR_DOUBLE: PRF("%e", cb->v.dbl); break; 82 case CN_CBOR_SIMPLE: PRF("simple(%ld)", cb->v.sint); break; 83 default: PRF("???%d???", cb->type); break; 84 } 85 *out++ = '\n'; 86 done: 87 *end = out; 88 } 89 90 91 const char *err_name[] = { 92 "CN_CBOR_NO_ERROR", 93 "CN_CBOR_ERR_OUT_OF_DATA", 94 "CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED", 95 "CN_CBOR_ERR_ODD_SIZE_INDEF_MAP", 96 "CN_CBOR_ERR_BREAK_OUTSIDE_INDEF", 97 "CN_CBOR_ERR_MT_UNDEF_FOR_INDEF", 98 "CN_CBOR_ERR_RESERVED_AI", 99 "CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING", 100 "CN_CBOR_ERR_OUT_OF_MEMORY", 101 "CN_CBOR_ERR_FLOAT_NOT_SUPPORTED", 102 }; 103 104 static void cn_cbor_decode_test(const unsigned char *buf, int len) { 105 struct cn_cbor_errback back; 106 const cn_cbor *ret = cn_cbor_decode(buf, len CBOR_CONTEXT_PARAM, &back); 107 if (ret) 108 printf("oops 1"); 109 printf("%s at %d\n", err_name[back.err], back.pos); 110 } 111 112 int main() { 113 char buf[100000]; 114 unsigned char *end; 115 char *bufend; 116 unsigned char *s = load_file("cases.cbor", &end); 117 printf("%zd\n", end-s); 118 cn_cbor *cb = cn_cbor_decode(s, end-s CBOR_CONTEXT_PARAM, 0); 119 if (cb) { 120 dump(cb, buf, &bufend, 0); 121 *bufend = 0; 122 printf("%s\n", buf); 123 cn_cbor_free(cb CBOR_CONTEXT_PARAM); 124 cb = 0; /* for leaks testing */ 125 } 126 cn_cbor_decode_test((const unsigned char*)"\xff", 1); /* break outside indef */ 127 cn_cbor_decode_test((const unsigned char*)"\x1f", 1); /* mt undef for indef */ 128 cn_cbor_decode_test((const unsigned char*)"\x00\x00", 2); /* not all data consumed */ 129 cn_cbor_decode_test((const unsigned char*)"\x81", 1); /* out of data */ 130 cn_cbor_decode_test((const unsigned char*)"\x1c", 1); /* reserved ai */ 131 cn_cbor_decode_test((const unsigned char*)"\xbf\x00\xff", 3); /* odd size indef map */ 132 cn_cbor_decode_test((const unsigned char*)"\x7f\x40\xff", 3); /* wrong nesting in indef string */ 133 system("leaks test"); 134 } 135 136 /* cn-cbor.c:112: CN_CBOR_FAIL("out of memory"); */ 137