diff --git a/include/neuron/json/json.h b/include/neuron/json/json.h index bfa3e452..aeca7768 100644 --- a/include/neuron/json/json.h +++ b/include/neuron/json/json.h @@ -37,17 +37,24 @@ typedef enum neu_json_type { NEU_JSON_FLOAT, NEU_JSON_BOOL, NEU_JSON_OBJECT, + NEU_JSON_BYTES, NEU_JSON_VALUE = NEU_JSON_UNDEFINE } neu_json_type_e; +typedef struct { + uint8_t *bytes; + uint8_t length; +} neu_json_value_bytes_t; + typedef union neu_json_value { - int64_t val_int; - uint8_t val_bit; - float val_float; - double val_double; - bool val_bool; - char * val_str; - void * val_object; + int64_t val_int; + uint8_t val_bit; + float val_float; + double val_double; + bool val_bool; + char * val_str; + void * val_object; + neu_json_value_bytes_t val_bytes; } neu_json_value_u; typedef enum neu_json_attribute { diff --git a/include/neuron/tag.h b/include/neuron/tag.h index d94861e5..25280d37 100644 --- a/include/neuron/tag.h +++ b/include/neuron/tag.h @@ -68,6 +68,10 @@ typedef union { neu_datatag_string_type_e type; } string; + struct { + uint8_t length; + } bytes; + struct { bool op; uint8_t bit; diff --git a/include/neuron/type.h b/include/neuron/type.h index 1769e97e..d8a95aed 100644 --- a/include/neuron/type.h +++ b/include/neuron/type.h @@ -105,21 +105,27 @@ typedef struct { } neu_value_ptr_t; #define NEU_VALUE_SIZE 128 + +typedef struct { + uint8_t bytes[NEU_VALUE_SIZE]; + uint8_t length; +} __attribute__((packed)) neu_value_bytes_t; + typedef union { - bool boolean; - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - int64_t i64; - uint64_t u64; - float f32; - double d64; - char str[NEU_VALUE_SIZE]; - uint8_t bytes[NEU_VALUE_SIZE]; - neu_value_ptr_t ptr; + bool boolean; + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + int64_t i64; + uint64_t u64; + float f32; + double d64; + char str[NEU_VALUE_SIZE]; + neu_value_bytes_t bytes; + neu_value_ptr_t ptr; } neu_value_u; static inline char *neu_value_str(neu_type_e type, neu_value_u value) diff --git a/plugins/ekuiper/json_rw.c b/plugins/ekuiper/json_rw.c index 5c8592d1..42df0813 100644 --- a/plugins/ekuiper/json_rw.c +++ b/plugins/ekuiper/json_rw.c @@ -118,6 +118,11 @@ int wrap_tag_data(neu_json_read_resp_tag_t * json_tag, json_tag->value.val_int = tag_value->value.value.i32; json_tag->error = tag_value->value.value.i32; break; + case NEU_TYPE_BYTES: + json_tag->t = NEU_JSON_BYTES; + json_tag->value.val_bytes.length = tag_value->value.value.bytes.length; + json_tag->value.val_bytes.bytes = tag_value->value.value.bytes.bytes; + break; default: break; } diff --git a/plugins/ekuiper/read_write.c b/plugins/ekuiper/read_write.c index 937c7b63..d02dd636 100644 --- a/plugins/ekuiper/read_write.c +++ b/plugins/ekuiper/read_write.c @@ -144,6 +144,12 @@ int write_data(neu_plugin_t *plugin, json_write_req_t *write_req) cmd.value.type = NEU_TYPE_BOOL; cmd.value.value.boolean = write_req->value.val_bool; break; + case NEU_JSON_BYTES: + cmd.value.type = NEU_TYPE_BYTES; + cmd.value.value.bytes.length = write_req->value.val_bytes.length; + memcpy(cmd.value.value.bytes.bytes, write_req->value.val_bytes.bytes, + write_req->value.val_bytes.length); + break; default: assert(false); break; diff --git a/plugins/modbus/modbus-rtu.json b/plugins/modbus/modbus-rtu.json index 4fbc5622..08ce55fc 100644 --- a/plugins/modbus/modbus-rtu.json +++ b/plugins/modbus/modbus-rtu.json @@ -39,6 +39,10 @@ { "type": 13, "regex": "^[0-9]+![3-4][0-9]+\\.[0-9]+(H|L|)$" + }, + { + "type": 14, + "regex": "^[0-9]+![3-4][0-9]+\\.[0-9]+$" } ], "group_interval": 1000, diff --git a/plugins/modbus/modbus-tcp.json b/plugins/modbus/modbus-tcp.json index 1a84bb51..d451c23d 100644 --- a/plugins/modbus/modbus-tcp.json +++ b/plugins/modbus/modbus-tcp.json @@ -39,6 +39,10 @@ { "type": 13, "regex": "^[0-9]+![3-4][0-9]+\\.[0-9]+(H|L|)$" + }, + { + "type": 14, + "regex": "^[0-9]+![3-4][0-9]+\\.[0-9]+$" } ], "group_interval": 1000, diff --git a/plugins/modbus/modbus_point.c b/plugins/modbus/modbus_point.c index ab2bfb04..a5dd4aa9 100644 --- a/plugins/modbus/modbus_point.c +++ b/plugins/modbus/modbus_point.c @@ -96,6 +96,9 @@ int modbus_tag_to_point(const neu_datatag_t *tag, modbus_point_t *point) point->option.string.length <= 0) { return NEU_ERR_TAG_ADDRESS_FORMAT_INVALID; } + if (point->type == NEU_TYPE_BYTES && point->option.bytes.length <= 0) { + return NEU_ERR_TAG_ADDRESS_FORMAT_INVALID; + } if (point->type == NEU_TYPE_BIT && point->option.bit.bit > 15) { return NEU_ERR_TAG_ADDRESS_FORMAT_INVALID; } @@ -160,6 +163,18 @@ int modbus_tag_to_point(const neu_datatag_t *tag, modbus_point_t *point) } } break; + case NEU_TYPE_BYTES: + if (point->area == MODBUS_AREA_COIL || + point->area == MODBUS_AREA_INPUT) { + ret = NEU_ERR_TAG_TYPE_NOT_SUPPORT; + } else { + if (point->option.bytes.length > 128) { + return NEU_ERR_TAG_ADDRESS_FORMAT_INVALID; + } + point->n_register = + point->option.bytes.length / 2 + point->option.bytes.length % 2; + } + break; default: return NEU_ERR_TAG_TYPE_NOT_SUPPORT; } @@ -246,6 +261,10 @@ int cal_n_byte(int type, neu_value_u *value, neu_datatag_addr_option_u option) } break; } + case NEU_TYPE_BYTES: { + n = option.bytes.length; + break; + } default: assert(1 == 0); break; diff --git a/plugins/modbus/modbus_req.c b/plugins/modbus/modbus_req.c index 226dc8b0..c7d8d669 100644 --- a/plugins/modbus/modbus_req.c +++ b/plugins/modbus/modbus_req.c @@ -367,10 +367,11 @@ int modbus_value_handle(void *ctx, uint8_t slave_id, uint16_t n_byte, case MODBUS_AREA_INPUT_REGISTER: if (n_byte >= ((*p_tag)->start_address - start_address) * 2 + (*p_tag)->n_register * 2) { - memcpy(dvalue.value.bytes, + memcpy(dvalue.value.bytes.bytes, bytes + ((*p_tag)->start_address - start_address) * 2, (*p_tag)->n_register * 2); + dvalue.value.bytes.length = (*p_tag)->n_register * 2; } break; case MODBUS_AREA_COIL: @@ -406,7 +407,7 @@ int modbus_value_handle(void *ctx, uint8_t slave_id, uint16_t n_byte, case MODBUS_AREA_HOLD_REGISTER: case MODBUS_AREA_INPUT_REGISTER: { neu_value16_u v16 = { 0 }; - v16.value = htons(*(uint16_t *) dvalue.value.bytes); + v16.value = htons(*(uint16_t *) dvalue.value.bytes.bytes); dvalue.value.u8 = neu_value16_get_bit(v16, (*p_tag)->option.bit.bit); break; @@ -495,15 +496,19 @@ int modbus_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag, n_byte = point.option.string.length; break; } + case NEU_TYPE_BYTES: { + n_byte = point.option.bytes.length; + break; + } default: assert(1 == 0); break; } uint16_t response_size = 0; - ret = modbus_stack_write(plugin->stack, req, point.slave_id, point.area, - point.start_address, point.n_register, value.bytes, - n_byte, &response_size, response); + ret = modbus_stack_write( + plugin->stack, req, point.slave_id, point.area, point.start_address, + point.n_register, value.bytes.bytes, n_byte, &response_size, response); if (ret > 0) { process_protocol_buf(plugin, point.slave_id, response_size); } diff --git a/plugins/mqtt/mqtt_handle.c b/plugins/mqtt/mqtt_handle.c index 5aa24a0e..111f1906 100644 --- a/plugins/mqtt/mqtt_handle.c +++ b/plugins/mqtt/mqtt_handle.c @@ -129,6 +129,12 @@ static int tag_values_to_json(neu_resp_tag_value_meta_t *tags, uint16_t len, json->tags[i].t = NEU_JSON_STR; json->tags[i].value.val_str = (char *) tag->value.value.ptr.ptr; break; + case NEU_TYPE_BYTES: + json->tags[i].t = NEU_JSON_BYTES; + json->tags[i].value.val_bytes.length = + tag->value.value.bytes.length; + json->tags[i].value.val_bytes.bytes = tag->value.value.bytes.bytes; + break; default: break; } @@ -269,6 +275,12 @@ static int send_write_tag_req(neu_plugin_t *plugin, neu_json_mqtt_t *mqtt, cmd.value.type = NEU_TYPE_BOOL; cmd.value.value.boolean = req->value.val_bool; break; + case NEU_JSON_BYTES: + cmd.value.type = NEU_TYPE_BYTES; + cmd.value.value.bytes.length = req->value.val_bytes.length; + memcpy(cmd.value.value.bytes.bytes, req->value.val_bytes.bytes, + req->value.val_bytes.length); + break; default: plog_error(plugin, "invalid tag value type: %d", req->t); return -1; @@ -329,6 +341,14 @@ static int send_write_tags_req(neu_plugin_t *plugin, neu_json_mqtt_t *mqtt, cmd.tags[i].value.type = NEU_TYPE_BOOL; cmd.tags[i].value.value.boolean = req->tags[i].value.val_bool; break; + case NEU_JSON_BYTES: + cmd.tags[i].value.type = NEU_TYPE_BYTES; + cmd.tags[i].value.value.bytes.length = + req->tags[i].value.val_bytes.length; + memcpy(cmd.tags[i].value.value.bytes.bytes, + req->tags[i].value.val_bytes.bytes, + req->tags[i].value.val_bytes.length); + break; default: plog_error(plugin, "invalid tag value type: %d", req->tags[i].t); free(cmd.tags); diff --git a/plugins/restful/rw_handle.c b/plugins/restful/rw_handle.c index ceb64ef5..e4887949 100644 --- a/plugins/restful/rw_handle.c +++ b/plugins/restful/rw_handle.c @@ -70,6 +70,15 @@ void handle_write(nng_aio *aio) return; } + if (req->t == NEU_JSON_BYTES && + req->value.val_bytes.length > NEU_VALUE_SIZE) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_STRING_TOO_LONG, { + neu_http_response(aio, NEU_ERR_STRING_TOO_LONG, + result_error); + }); + return; + } + header.ctx = aio; header.type = NEU_REQ_WRITE_TAG; @@ -86,6 +95,12 @@ void handle_write(nng_aio *aio) cmd.value.type = NEU_TYPE_STRING; strcpy(cmd.value.value.str, req->value.val_str); break; + case NEU_JSON_BYTES: + cmd.value.type = NEU_TYPE_BYTES; + cmd.value.value.bytes.length = req->value.val_bytes.length; + memcpy(cmd.value.value.bytes.bytes, req->value.val_bytes.bytes, + req->value.val_bytes.length); + break; case NEU_JSON_DOUBLE: cmd.value.type = NEU_TYPE_DOUBLE; cmd.value.value.d64 = req->value.val_double; @@ -158,6 +173,14 @@ void handle_write_tags(nng_aio *aio) cmd.tags[i].value.value.boolean = req->tags[i].value.val_bool; break; + case NEU_JSON_BYTES: + cmd.tags[i].value.type = NEU_TYPE_BYTES; + cmd.tags[i].value.value.bytes.length = + req->tags[i].value.val_bytes.length; + memcpy(cmd.tags[i].value.value.bytes.bytes, + req->tags[i].value.val_bytes.bytes, + req->tags[i].value.val_bytes.length); + break; default: assert(false); break; @@ -260,6 +283,13 @@ void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp) api_res.tags[i].t = NEU_JSON_STR; api_res.tags[i].value.val_str = resp->tags[i].value.value.str; break; + case NEU_TYPE_BYTES: + api_res.tags[i].t = NEU_JSON_BYTES; + api_res.tags[i].value.val_bytes.length = + resp->tags[i].value.value.bytes.length; + api_res.tags[i].value.val_bytes.bytes = + resp->tags[i].value.value.bytes.bytes; + break; case NEU_TYPE_ERROR: api_res.tags[i].t = NEU_JSON_INT; api_res.tags[i].value.val_int = resp->tags[i].value.value.i32; diff --git a/src/adapter/driver/cache.c b/src/adapter/driver/cache.c index a21573a1..ee5ad77e 100644 --- a/src/adapter/driver/cache.c +++ b/src/adapter/driver/cache.c @@ -159,7 +159,6 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache, case NEU_TYPE_BIT: case NEU_TYPE_BOOL: case NEU_TYPE_STRING: - case NEU_TYPE_BYTES: case NEU_TYPE_WORD: case NEU_TYPE_DWORD: case NEU_TYPE_LWORD: @@ -168,6 +167,18 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache, elem->changed = true; } break; + case NEU_TYPE_BYTES: + if (elem->value.value.bytes.length != + value.value.bytes.length) { + elem->changed = true; + } else { + if (memcpy(elem->value.value.bytes.bytes, + value.value.bytes.bytes, + value.value.bytes.length) != 0) { + elem->changed = true; + } + } + break; case NEU_TYPE_PTR: { if (elem->value.value.ptr.length != value.value.ptr.length) { elem->changed = true; @@ -290,10 +301,15 @@ int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group, value->value.value.boolean = elem->value.value.boolean; break; case NEU_TYPE_STRING: - case NEU_TYPE_BYTES: memcpy(value->value.value.str, elem->value.value.str, sizeof(elem->value.value.str)); break; + case NEU_TYPE_BYTES: + value->value.value.bytes.length = elem->value.value.bytes.length; + memcpy(value->value.value.bytes.bytes, + elem->value.value.bytes.bytes, + elem->value.value.bytes.length); + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; @@ -368,10 +384,15 @@ int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache, value->value.value.boolean = elem->value.value.boolean; break; case NEU_TYPE_STRING: - case NEU_TYPE_BYTES: memcpy(value->value.value.str, elem->value.value.str, sizeof(elem->value.value.str)); break; + case NEU_TYPE_BYTES: + value->value.value.bytes.length = elem->value.value.bytes.length; + memcpy(value->value.value.bytes.bytes, + elem->value.value.bytes.bytes, + elem->value.value.bytes.length); + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; @@ -444,10 +465,15 @@ int neu_driver_cache_get(neu_driver_cache_t *cache, const char *group, value->value.value.boolean = elem->value.value.boolean; break; case NEU_TYPE_STRING: - case NEU_TYPE_BYTES: memcpy(value->value.value.str, elem->value.value.str, sizeof(elem->value.value.str)); break; + case NEU_TYPE_BYTES: + value->value.value.bytes.length = elem->value.value.bytes.length; + memcpy(value->value.value.bytes.bytes, + elem->value.value.bytes.bytes, + elem->value.value.bytes.length); + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; @@ -518,10 +544,15 @@ int neu_driver_cache_get_changed(neu_driver_cache_t *cache, const char *group, value->value.value.boolean = elem->value.value.boolean; break; case NEU_TYPE_STRING: - case NEU_TYPE_BYTES: memcpy(value->value.value.str, elem->value.value.str, sizeof(elem->value.value.str)); break; + case NEU_TYPE_BYTES: + value->value.value.bytes.length = elem->value.value.bytes.length; + memcpy(value->value.value.bytes.bytes, + elem->value.value.bytes.bytes, + elem->value.value.bytes.length); + break; case NEU_TYPE_PTR: value->value.value.ptr.length = elem->value.value.ptr.length; value->value.value.ptr.type = elem->value.value.ptr.type; diff --git a/src/adapter/driver/driver.c b/src/adapter/driver/driver.c index 7293b831..1a73a561 100644 --- a/src/adapter/driver/driver.c +++ b/src/adapter/driver/driver.c @@ -378,6 +378,7 @@ static void fix_value(neu_datatag_t *tag, neu_type_e value_type, switch (tag->type) { case NEU_TYPE_BOOL: case NEU_TYPE_STRING: + case NEU_TYPE_BYTES: break; case NEU_TYPE_BIT: value->type = NEU_TYPE_BIT; @@ -404,16 +405,16 @@ static void fix_value(neu_datatag_t *tag, neu_type_e value_type, value->value.u32 = (uint32_t) value->value.u64; switch (tag->option.value32.endian) { case NEU_DATATAG_ENDIAN_LB32: - neu_ntohs_p((uint16_t *) value->value.bytes); - neu_ntohs_p((uint16_t *) value->value.bytes + 2); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes + 2); break; case NEU_DATATAG_ENDIAN_BB32: value->value.u32 = htonl(value->value.u32); break; case NEU_DATATAG_ENDIAN_BL32: value->value.u32 = htonl(value->value.u32); - neu_ntohs_p((uint16_t *) value->value.bytes); - neu_ntohs_p((uint16_t *) value->value.bytes + 2); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes + 2); break; case NEU_DATATAG_ENDIAN_LL32: default: @@ -428,16 +429,16 @@ static void fix_value(neu_datatag_t *tag, neu_type_e value_type, switch (tag->option.value32.endian) { case NEU_DATATAG_ENDIAN_LB32: - neu_ntohs_p((uint16_t *) value->value.bytes); - neu_ntohs_p((uint16_t *) value->value.bytes + 2); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes + 2); break; case NEU_DATATAG_ENDIAN_BB32: value->value.u32 = htonl(value->value.u32); break; case NEU_DATATAG_ENDIAN_BL32: value->value.u32 = htonl(value->value.u32); - neu_ntohs_p((uint16_t *) value->value.bytes); - neu_ntohs_p((uint16_t *) value->value.bytes + 2); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes); + neu_ntohs_p((uint16_t *) value->value.bytes.bytes + 2); break; case NEU_DATATAG_ENDIAN_LL32: default: @@ -1374,8 +1375,8 @@ static int read_report_group(int64_t timestamp, int64_t timeout, case NEU_TYPE_INT32: switch (tag->option.value32.endian) { case NEU_DATATAG_ENDIAN_LB32: { - uint16_t *v1 = (uint16_t *) value.value.value.bytes; - uint16_t *v2 = (uint16_t *) (value.value.value.bytes + 2); + uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes; + uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2); neu_htons_p(v1); neu_htons_p(v2); @@ -1386,8 +1387,8 @@ static int read_report_group(int64_t timestamp, int64_t timeout, break; case NEU_DATATAG_ENDIAN_BL32: value.value.value.u32 = htonl(value.value.value.u32); - uint16_t *v1 = (uint16_t *) value.value.value.bytes; - uint16_t *v2 = (uint16_t *) (value.value.value.bytes + 2); + uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes; + uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2); neu_htons_p(v1); neu_htons_p(v2); @@ -1523,8 +1524,8 @@ static void read_group(int64_t timestamp, int64_t timeout, case NEU_TYPE_INT32: switch (tag->option.value32.endian) { case NEU_DATATAG_ENDIAN_LB32: { - uint16_t *v1 = (uint16_t *) value.value.value.bytes; - uint16_t *v2 = (uint16_t *) (value.value.value.bytes + 2); + uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes; + uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2); neu_htons_p(v1); neu_htons_p(v2); @@ -1535,8 +1536,8 @@ static void read_group(int64_t timestamp, int64_t timeout, break; case NEU_DATATAG_ENDIAN_BL32: value.value.value.u32 = htonl(value.value.value.u32); - uint16_t *v1 = (uint16_t *) value.value.value.bytes; - uint16_t *v2 = (uint16_t *) (value.value.value.bytes + 2); + uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes; + uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2); neu_htons_p(v1); neu_htons_p(v2); diff --git a/src/base/tag.c b/src/base/tag.c index faa4b852..d349b56f 100644 --- a/src/base/tag.c +++ b/src/base/tag.c @@ -137,6 +137,19 @@ int neu_datatag_parse_addr_option(const neu_datatag_t * datatag, int ret = 0; switch (datatag->type) { + case NEU_TYPE_BYTES: { + char *op = find_last_character(datatag->address, '.'); + + if (op == NULL) { + ret = -1; + } else { + int n = sscanf(op, ".%hhd", &option->bytes.length); + if (n != 1 || option->string.length <= 0) { + ret = -1; + } + } + break; + } case NEU_TYPE_STRING: { char *op = find_last_character(datatag->address, '.'); diff --git a/src/parser/neu_json_rw.c b/src/parser/neu_json_rw.c index 58668a4f..ef86f656 100644 --- a/src/parser/neu_json_rw.c +++ b/src/parser/neu_json_rw.c @@ -233,6 +233,9 @@ void neu_json_decode_write_req_free(neu_json_write_req_t *req) if (req->t == NEU_JSON_STR) { free(req->value.val_str); } + if (req->t == NEU_JSON_BYTES && req->value.val_bytes.length > 0) { + free(req->value.val_bytes.bytes); + } free(req); } @@ -346,6 +349,10 @@ void neu_json_decode_write_tags_req_free(neu_json_write_tags_req_t *req) if (req->tags[i].t == NEU_JSON_STR) { free(req->tags[i].value.val_str); } + if (req->tags[i].t == NEU_JSON_BYTES && + req->tags[i].value.val_bytes.length > 0) { + free(req->tags[i].value.val_bytes.bytes); + } } free(req->tags); free(req); diff --git a/src/utils/json.c b/src/utils/json.c index 454c8245..66fb94b9 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -80,6 +80,17 @@ static json_t *encode_object(json_t *object, neu_json_elem_t ele) case NEU_JSON_BOOL: json_object_set_new(ob, ele.name, json_boolean(ele.v.val_bool)); break; + case NEU_JSON_BYTES: { + void *bytes = json_array(); + + for (int i = 0; i < ele.v.val_bytes.length; i++) { + json_array_append_new(bytes, + json_integer(ele.v.val_bytes.bytes[i])); + } + + json_object_set_new(ob, ele.name, bytes); + break; + } case NEU_JSON_OBJECT: json_object_set_new(ob, ele.name, ele.v.val_object); break; @@ -117,6 +128,8 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) ele->t = NEU_JSON_BOOL; } else if (json_is_integer(ob)) { ele->t = NEU_JSON_INT; + } else if (json_is_array(ob)) { + ele->t = NEU_JSON_BYTES; } } @@ -147,6 +160,23 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) case NEU_JSON_BOOL: ele->v.val_bool = json_boolean_value(ob); break; + case NEU_JSON_BYTES: { + json_t *value = NULL; + + ele->v.val_bytes.length = json_array_size(ob); + if (ele->v.val_bytes.length > 0) { + int index = 0; + + ele->v.val_bytes.bytes = + calloc(ele->v.val_bytes.length, sizeof(uint8_t)); + json_array_foreach(ob, index, value) + { + ele->v.val_bytes.bytes[index] = + (uint8_t) json_integer_value(value); + } + } + break; + } case NEU_JSON_OBJECT: ele->v.val_object = ob; break;