Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
cn-cbor.c
00001 #ifndef CN_CBOR_C 00002 #define CN_CBOR_C 00003 00004 #ifdef __cplusplus 00005 extern "C" { 00006 #endif 00007 #ifdef EMACS_INDENTATION_HELPER 00008 } /* Duh. */ 00009 #endif 00010 00011 #include <stdlib.h> 00012 #include <stdint.h> 00013 #include <string.h> 00014 #include <assert.h> 00015 #include <math.h> 00016 #ifdef CBOR_CAN_DO_UNALIGNED_READS 00017 #include <arpa/inet.h> // needed for ntohl (e.g.) on Linux 00018 #endif 00019 00020 #include "cn-cbor.h" 00021 #include "cbor.h" 00022 00023 00024 #define CN_CBOR_FAIL(code) do { pb->err = code; goto fail; } while(0) 00025 00026 void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT) { 00027 cn_cbor* p = cb; 00028 assert(!p || !p->parent); 00029 while (p) { 00030 cn_cbor* p1; 00031 p1 = p->first_child; 00032 while ((p1)) { /* go down */ 00033 p = p1; 00034 p1 = p->first_child; 00035 } 00036 p1 = p->next; 00037 if (!(p1)) { /* go up next */ 00038 p1 = p->parent; 00039 if ((p1)) 00040 p1->first_child = 0; 00041 } 00042 CN_CBOR_FREE_CONTEXT(p); 00043 p = p1; 00044 } 00045 } 00046 00047 #ifndef CBOR_NO_FLOAT 00048 static double decode_half(int half) { 00049 int exp = (half >> 10) & 0x1f; 00050 int mant = half & 0x3ff; 00051 double val = 0; 00052 if (exp == 0) { 00053 val = ldexp(mant, -24); 00054 } else if (exp != 31) { 00055 val = ldexp(mant + 1024, exp - 25); 00056 } else { 00057 if (mant == 0) { 00058 val = INFINITY; 00059 } else { 00060 val = NAN; 00061 } 00062 } 00063 return half & 0x8000 ? -val : val; 00064 } 00065 #endif /* CBOR_NO_FLOAT */ 00066 00067 /* Fix these if you can't do non-aligned reads */ 00068 #define ntoh8p(p) (*(unsigned char*)(p)) 00069 #ifdef CBOR_CAN_DO_UNALIGNED_READS 00070 #define ntoh16p(p) (ntohs(*(unsigned short*)(p))) 00071 #define ntoh32p(p) (ntohl(*(unsigned long*)(p))) 00072 #else 00073 static uint16_t ntoh16p(unsigned char *p) { 00074 uint16_t ret = ntoh8p(p); 00075 ret <<= 8; 00076 ret += ntoh8p(p+1); 00077 return ret; 00078 } 00079 static uint32_t ntoh32p(unsigned char *p) { 00080 uint64_t ret = ntoh16p(p); 00081 ret <<= 16; 00082 ret += ntoh16p(p+2); 00083 return ret; 00084 } 00085 #endif 00086 static uint64_t ntoh64p(unsigned char *p) { 00087 uint64_t ret = ntoh32p(p); 00088 ret <<= 32; 00089 ret += ntoh32p(p+4); 00090 return ret; 00091 } 00092 00093 static cn_cbor_type mt_trans[] = { 00094 CN_CBOR_UINT, CN_CBOR_INT, 00095 CN_CBOR_BYTES, CN_CBOR_TEXT, 00096 CN_CBOR_ARRAY, CN_CBOR_MAP, 00097 CN_CBOR_TAG, CN_CBOR_SIMPLE, 00098 }; 00099 00100 struct parse_buf { 00101 unsigned char *buf; 00102 unsigned char *ebuf; 00103 cn_cbor_error err; 00104 }; 00105 00106 #define TAKE(pos, ebuf, n, stmt) \ 00107 if (n > (size_t)(ebuf - pos)) \ 00108 CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_DATA); \ 00109 stmt; \ 00110 pos += n; 00111 00112 static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_parent) { 00113 unsigned char *pos = pb->buf; 00114 unsigned char *ebuf = pb->ebuf; 00115 cn_cbor* parent = top_parent; 00116 int ib; 00117 unsigned int mt; 00118 int ai; 00119 uint64_t val; 00120 cn_cbor* cb = NULL; 00121 #ifndef CBOR_NO_FLOAT 00122 union { 00123 float f; 00124 uint32_t u; 00125 } u32; 00126 union { 00127 double d; 00128 uint64_t u; 00129 } u64; 00130 #endif /* CBOR_NO_FLOAT */ 00131 00132 again: 00133 TAKE(pos, ebuf, 1, ib = ntoh8p(pos) ); 00134 if (ib == IB_BREAK) { 00135 if (!(parent->flags & CN_CBOR_FL_INDEF)) 00136 CN_CBOR_FAIL(CN_CBOR_ERR_BREAK_OUTSIDE_INDEF); 00137 switch (parent->type) { 00138 case CN_CBOR_BYTES: case CN_CBOR_TEXT: 00139 parent->type += 2; /* CN_CBOR_* -> CN_CBOR_*_CHUNKED */ 00140 break; 00141 case CN_CBOR_MAP: 00142 if (parent->length & 1) 00143 CN_CBOR_FAIL(CN_CBOR_ERR_ODD_SIZE_INDEF_MAP); 00144 default:; 00145 } 00146 goto complete; 00147 } 00148 mt = ib >> 5; 00149 ai = ib & 0x1f; 00150 val = ai; 00151 00152 cb = CN_CALLOC_CONTEXT(); 00153 if (!cb) 00154 CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_MEMORY); 00155 00156 cb->type = mt_trans[mt]; 00157 00158 cb->parent = parent; 00159 if (parent->last_child) { 00160 parent->last_child->next = cb; 00161 } else { 00162 parent->first_child = cb; 00163 } 00164 parent->last_child = cb; 00165 parent->length++; 00166 00167 switch (ai) { 00168 case AI_1: TAKE(pos, ebuf, 1, val = ntoh8p(pos)) ; cb->length = 1; break; 00169 case AI_2: TAKE(pos, ebuf, 2, val = ntoh16p(pos)) ; cb->length = 2; break; 00170 case AI_4: TAKE(pos, ebuf, 4, val = ntoh32p(pos)) ; cb->length = 4; break; 00171 case AI_8: TAKE(pos, ebuf, 8, val = ntoh64p(pos)) ; cb->length = 8; break; 00172 00173 case 28: case 29: case 30: CN_CBOR_FAIL(CN_CBOR_ERR_RESERVED_AI); 00174 case AI_INDEF: 00175 if ((mt - MT_BYTES) <= MT_MAP) { 00176 cb->flags |= CN_CBOR_FL_INDEF; 00177 goto push; 00178 } else { 00179 CN_CBOR_FAIL(CN_CBOR_ERR_MT_UNDEF_FOR_INDEF); 00180 } 00181 } 00182 // process content 00183 switch (mt) { 00184 case MT_UNSIGNED: 00185 cb->v.uint = val; /* to do: Overflow check */ 00186 /* 00187 if the integer itsef is used (ai=0..23), set the length to 4, for compliance 00188 with the definition that integer values of mbed.UseBootstrap and mbed.MemoryTotalKB 00189 is 4 bytes. 00190 This implementation might cause bugs with other parameters that has no such requirement, 00191 so the code should be changed in the future 00192 */ 00193 if (cb->length == 0) { 00194 cb->length = 4; 00195 } 00196 break; 00197 case MT_NEGATIVE: 00198 cb->v.sint = ~val; /* to do: Overflow check */ 00199 /* 00200 if the integer itsef is used (ai=0..23), set the length to 4, for compliance 00201 with the definition that integer values of mbed.UseBootstrap and mbed.MemoryTotalKB 00202 is 4 bytes. 00203 This implementation might cause bugs with other parameters that has no such requirement, 00204 so the code should be changed in the future 00205 */ 00206 if (cb->length == 0) { 00207 cb->length = 4; 00208 } 00209 break; 00210 case MT_BYTES: case MT_TEXT: 00211 cb->v.str = (char *) pos; 00212 cb->length = val; 00213 TAKE(pos, ebuf, val, ;); 00214 break; 00215 case MT_MAP: 00216 val <<= 1; 00217 /* fall through */ 00218 case MT_ARRAY: 00219 cb->v.count = val; 00220 if ((cb->v.count)) { 00221 cb->flags |= CN_CBOR_FL_COUNT; 00222 goto push; 00223 } 00224 break; 00225 case MT_TAG: 00226 cb->v.uint = val; 00227 goto push; 00228 case MT_PRIM: 00229 switch (ai) { 00230 case VAL_FALSE: cb->type = CN_CBOR_FALSE; break; 00231 case VAL_TRUE: cb->type = CN_CBOR_TRUE; break; 00232 case VAL_NIL: cb->type = CN_CBOR_NULL; break; 00233 case VAL_UNDEF: cb->type = CN_CBOR_UNDEF; break; 00234 case AI_2: 00235 #ifndef CBOR_NO_FLOAT 00236 cb->type = CN_CBOR_DOUBLE; 00237 cb->v.dbl = decode_half(val); 00238 #else /* CBOR_NO_FLOAT */ 00239 CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED); 00240 #endif /* CBOR_NO_FLOAT */ 00241 break; 00242 case AI_4: 00243 #ifndef CBOR_NO_FLOAT 00244 cb->type = CN_CBOR_DOUBLE; 00245 u32.u = val; 00246 cb->v.dbl = u32.f; 00247 #else /* CBOR_NO_FLOAT */ 00248 CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED); 00249 #endif /* CBOR_NO_FLOAT */ 00250 break; 00251 case AI_8: 00252 #ifndef CBOR_NO_FLOAT 00253 cb->type = CN_CBOR_DOUBLE; 00254 u64.u = val; 00255 cb->v.dbl = u64.d; 00256 #else /* CBOR_NO_FLOAT */ 00257 CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED); 00258 #endif /* CBOR_NO_FLOAT */ 00259 break; 00260 default: cb->v.uint = val; 00261 } 00262 } 00263 fill: /* emulate loops */ 00264 if (parent->flags & CN_CBOR_FL_INDEF) { 00265 if (parent->type == CN_CBOR_BYTES || parent->type == CN_CBOR_TEXT) 00266 if (cb->type != parent->type) 00267 CN_CBOR_FAIL(CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING); 00268 goto again; 00269 } 00270 if (parent->flags & CN_CBOR_FL_COUNT) { 00271 if (--parent->v.count) 00272 goto again; 00273 } 00274 /* so we are done filling parent. */ 00275 complete: /* emulate return from call */ 00276 if (parent == top_parent) { 00277 if (pos != ebuf) /* XXX do this outside */ 00278 CN_CBOR_FAIL(CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED); 00279 pb->buf = pos; 00280 return cb; 00281 } 00282 cb = parent; 00283 parent = parent->parent; 00284 goto fill; 00285 push: /* emulate recursive call */ 00286 parent = cb; 00287 goto again; 00288 fail: 00289 pb->buf = pos; 00290 return 0; 00291 } 00292 00293 cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp) { 00294 cn_cbor catcher; 00295 struct parse_buf pb; 00296 cn_cbor* ret; 00297 00298 memset(&catcher,0 , sizeof(cn_cbor)); 00299 catcher.type = CN_CBOR_INVALID; 00300 pb.buf = (unsigned char *)buf; 00301 pb.ebuf = (unsigned char *)buf+len; 00302 pb.err = CN_CBOR_NO_ERROR; 00303 ret = decode_item(&pb CBOR_CONTEXT_PARAM, &catcher); 00304 if (ret != NULL) { 00305 /* mark as top node */ 00306 ret->parent = NULL; 00307 } else { 00308 00309 if (catcher.first_child) { 00310 catcher.first_child->parent = 0; 00311 cn_cbor_free(catcher.first_child CBOR_CONTEXT_PARAM); 00312 } 00313 //fail: 00314 if (errp) { 00315 errp->err = pb.err; 00316 errp->pos = pb.buf - (unsigned char *)buf; 00317 } 00318 return NULL; 00319 } 00320 return ret; 00321 } 00322 00323 00324 #ifdef __cplusplus 00325 } 00326 #endif 00327 00328 #endif /* CN_CBOR_C */
Generated on Tue Jul 12 2022 19:12:11 by 1.7.2