Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 
    