static int cbor_internal_read_object(CborValue *root_value, const struct cbor_attr_t *attrs, const struct cbor_array_t *parent, int offset) { const struct cbor_attr_t *cursor, *best_match; char attrbuf[MYNEWT_VAL(CBORATTR_MAX_SIZE) + 1]; void *lptr; CborValue cur_value; CborError err = 0; size_t len; CborType type = CborInvalidType; /* stuff fields with defaults in case they're omitted in the JSON input */ for (cursor = attrs; cursor->attribute != NULL; cursor++) { if (!cursor->nodefault) { lptr = cbor_target_address(cursor, parent, offset); if (lptr != NULL) { switch (cursor->type) { case CborAttrIntegerType: memcpy(lptr, &cursor->dflt.integer, sizeof(long long int)); break; case CborAttrUnsignedIntegerType: memcpy(lptr, &cursor->dflt.integer, sizeof(long long unsigned int)); break; case CborAttrBooleanType: memcpy(lptr, &cursor->dflt.boolean, sizeof(bool)); break; #if FLOAT_SUPPORT case CborAttrFloatType: memcpy(lptr, &cursor->dflt.fval, sizeof(float)); break; case CborAttrDoubleType: memcpy(lptr, &cursor->dflt.real, sizeof(double)); break; #endif default: break; } } } } if (cbor_value_is_map(root_value)) { err |= cbor_value_enter_container(root_value, &cur_value); } else { err |= CborErrorIllegalType; return err; } /* contains key value pairs */ while (cbor_value_is_valid(&cur_value) && !err) { /* get the attribute */ if (cbor_value_is_text_string(&cur_value)) { if (cbor_value_calculate_string_length(&cur_value, &len) == 0) { if (len > MYNEWT_VAL(CBORATTR_MAX_SIZE)) { err |= CborErrorDataTooLarge; break; } err |= cbor_value_copy_text_string(&cur_value, attrbuf, &len, NULL); } /* at least get the type of the next value so we can match the * attribute name and type for a perfect match */ err |= cbor_value_advance(&cur_value); if (cbor_value_is_valid(&cur_value)) { type = cbor_value_get_type(&cur_value); } else { err |= CborErrorIllegalType; break; } } else { attrbuf[0] = '\0'; type = cbor_value_get_type(&cur_value); } /* find this attribute in our list */ best_match = NULL; for (cursor = attrs; cursor->attribute != NULL; cursor++) { if (valid_attr_type(type, cursor->type)) { if (cursor->attribute == CBORATTR_ATTR_UNNAMED && attrbuf[0] == '\0') { best_match = cursor; } else if (strlen(cursor->attribute) == len && !memcmp(cursor->attribute, attrbuf, len)) { break; } } } if (!cursor->attribute && best_match) { cursor = best_match; } /* we found a match */ if (cursor->attribute != NULL) { lptr = cbor_target_address(cursor, parent, offset); switch (cursor->type) { case CborAttrNullType: /* nothing to do */ break; case CborAttrBooleanType: err |= cbor_value_get_boolean(&cur_value, lptr); break; case CborAttrIntegerType: err |= cbor_value_get_int64(&cur_value, lptr); break; case CborAttrUnsignedIntegerType: err |= cbor_value_get_uint64(&cur_value, lptr); break; #if FLOAT_SUPPORT case CborAttrFloatType: err |= cbor_value_get_float(&cur_value, lptr); break; case CborAttrDoubleType: err |= cbor_value_get_double(&cur_value, lptr); break; #endif case CborAttrByteStringType: { size_t len = cursor->len; err |= cbor_value_copy_byte_string(&cur_value, lptr, &len, NULL); *cursor->addr.bytestring.len = len; break; } case CborAttrTextStringType: { size_t len = cursor->len; err |= cbor_value_copy_text_string(&cur_value, lptr, &len, NULL); break; } case CborAttrArrayType: err |= cbor_read_array(&cur_value, &cursor->addr.array); continue; case CborAttrObjectType: err |= cbor_internal_read_object(&cur_value, cursor->addr.obj, NULL, 0); continue; default: err |= CborErrorIllegalType; } } cbor_value_advance(&cur_value); } if (!err) { /* that should be it for this container */ err |= cbor_value_leave_container(root_value, &cur_value); } return err; }
/* Parse single property */ static void oc_parse_rep_value(CborValue *value, oc_rep_t **rep, CborError *err) { size_t k, len; CborValue map, array; *rep = _alloc_rep(); oc_rep_t *cur = *rep, **prev = 0; cur->next = 0; cur->value_object_array = 0; /* key */ *err |= cbor_value_calculate_string_length(value, &len); len++; oc_alloc_string(&cur->name, len); *err |= cbor_value_copy_text_string(value, (char *)oc_string(cur->name), &len, NULL); *err |= cbor_value_advance(value); /* value */ switch (value->type) { case CborIntegerType: *err |= cbor_value_get_int64(value, &cur->value_int); cur->type = INT; break; case CborBooleanType: *err |= cbor_value_get_boolean(value, &cur->value_boolean); cur->type = BOOL; break; case CborDoubleType: *err |= cbor_value_get_double(value, &cur->value_double); cur->type = DOUBLE; break; case CborByteStringType: *err |= cbor_value_calculate_string_length(value, &len); len++; oc_alloc_string(&cur->value_string, len); *err |= cbor_value_copy_byte_string( value, oc_cast(cur->value_string, uint8_t), &len, NULL); cur->type = BYTE_STRING; break; case CborTextStringType: *err |= cbor_value_calculate_string_length(value, &len); len++; oc_alloc_string(&cur->value_string, len); *err |= cbor_value_copy_text_string(value, oc_string(cur->value_string), &len, NULL); cur->type = STRING; break; case CborMapType: /* when value is a map/object */ { oc_rep_t **obj = &cur->value_object; // object points to list of properties *err |= cbor_value_enter_container(value, &map); while (!cbor_value_at_end(&map)) { oc_parse_rep_value(&map, obj, err); (*obj)->next = 0; obj = &(*obj)->next; *err |= cbor_value_advance(&map); } cur->type = OBJECT; } break; case CborArrayType: *err |= cbor_value_enter_container(value, &array); len = 0; cbor_value_get_array_length(value, &len); if (len == 0) { CborValue t = array; while (!cbor_value_at_end(&t)) { len++; cbor_value_advance(&t); } } k = 0; while (!cbor_value_at_end(&array)) { switch (array.type) { case CborIntegerType: if (k == 0) { oc_new_int_array(&cur->value_array, len); cur->type = INT | ARRAY; } *err |= cbor_value_get_int64(&array, oc_int_array(cur->value_array) + k); break; case CborDoubleType: if (k == 0) { oc_new_double_array(&cur->value_array, len); cur->type = DOUBLE | ARRAY; } *err |= cbor_value_get_double(&array, oc_double_array(cur->value_array) + k); break; case CborBooleanType: if (k == 0) { oc_new_bool_array(&cur->value_array, len); cur->type = BOOL | ARRAY; } *err |= cbor_value_get_boolean(&array, oc_bool_array(cur->value_array) + k); break; case CborByteStringType: if (k == 0) { oc_new_string_array(&cur->value_array, len); cur->type = BYTE_STRING | ARRAY; } *err |= cbor_value_calculate_string_length(&array, &len); len++; *err |= cbor_value_copy_byte_string( &array, (uint8_t *)oc_string_array_get_item(cur->value_array, k), &len, NULL); break; case CborTextStringType: if (k == 0) { oc_new_string_array(&cur->value_array, len); cur->type = STRING | ARRAY; } *err |= cbor_value_calculate_string_length(&array, &len); len++; *err |= cbor_value_copy_text_string( &array, (char *)oc_string_array_get_item(cur->value_array, k), &len, NULL); break; case CborMapType: if (k == 0) { cur->type = OBJECT | ARRAY; cur->value_object_array = _alloc_rep(); prev = &cur->value_object_array; } else { (*prev)->next = _alloc_rep(); prev = &(*prev)->next; } (*prev)->type = OBJECT; (*prev)->next = 0; oc_rep_t **obj = &(*prev)->value_object; /* Process a series of properties that make up an object of the array */ *err |= cbor_value_enter_container(&array, &map); while (!cbor_value_at_end(&map)) { oc_parse_rep_value(&map, obj, err); obj = &(*obj)->next; *err |= cbor_value_advance(&map); } break; default: break; } k++; *err |= cbor_value_advance(&array); } break; default: break; } }