mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 05:11:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			842 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			842 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2019 Intel Corporation.  All rights reserved.
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #include "attr_container.h"
 | |
| 
 | |
| typedef union jvalue {
 | |
|     bool z;
 | |
|     int8_t b;
 | |
|     uint16_t c;
 | |
|     int16_t s;
 | |
|     int32_t i;
 | |
|     int64_t j;
 | |
|     float f;
 | |
|     double d;
 | |
| } jvalue;
 | |
| 
 | |
| #define bh_memcpy_s(dest, dlen, src, slen) do {                         \
 | |
|     int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen);      \
 | |
|     (void)_ret;                                                         \
 | |
|   } while (0)
 | |
| 
 | |
| static inline int16_t get_int16(const char *buf)
 | |
| {
 | |
|     int16_t ret;
 | |
|     bh_memcpy_s(&ret, sizeof(int16_t), buf, sizeof(int16_t));
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static inline uint16_t get_uint16(const char *buf)
 | |
| {
 | |
|     return get_int16(buf);
 | |
| }
 | |
| 
 | |
| static inline int32_t get_int32(const char *buf)
 | |
| {
 | |
|     int32_t ret;
 | |
|     bh_memcpy_s(&ret, sizeof(int32_t), buf, sizeof(int32_t));
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static inline uint32_t get_uint32(const char *buf)
 | |
| {
 | |
|     return get_int32(buf);
 | |
| }
 | |
| 
 | |
| static inline int64_t get_int64(const char *buf)
 | |
| {
 | |
|     int64_t ret;
 | |
|     bh_memcpy_s(&ret, sizeof(int64_t), buf, sizeof(int64_t));
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static inline uint64_t get_uint64(const char *buf)
 | |
| {
 | |
|     return get_int64(buf);
 | |
| }
 | |
| 
 | |
| static inline void set_int16(char *buf, int16_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(int16_t), &v, sizeof(int16_t));
 | |
| }
 | |
| 
 | |
| static inline void set_uint16(char *buf, uint16_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(uint16_t), &v, sizeof(uint16_t));
 | |
| }
 | |
| 
 | |
| static inline void set_int32(char *buf, int32_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(int32_t), &v, sizeof(int32_t));
 | |
| }
 | |
| 
 | |
| static inline void set_uint32(char *buf, uint32_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(uint32_t), &v, sizeof(uint32_t));
 | |
| }
 | |
| 
 | |
| static inline void set_int64(char *buf, int64_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(int64_t), &v, sizeof(int64_t));
 | |
| }
 | |
| 
 | |
| static inline void set_uint64(char *buf, uint64_t v)
 | |
| {
 | |
|     bh_memcpy_s(buf, sizeof(uint64_t), &v, sizeof(uint64_t));
 | |
| }
 | |
| 
 | |
| char*
 | |
| attr_container_get_attr_begin(const attr_container_t *attr_cont,
 | |
|         uint32_t *p_total_length, uint16_t *p_attr_num)
 | |
| {
 | |
|     char *p = (char*) attr_cont->buf;
 | |
|     uint16_t str_len, attr_num;
 | |
|     uint32_t total_length;
 | |
| 
 | |
|     /* skip total length */
 | |
|     total_length = get_uint32(p);
 | |
|     p += sizeof(uint32_t);
 | |
|     if (!total_length)
 | |
|         return NULL;
 | |
| 
 | |
|     /* tag length */
 | |
|     str_len = get_uint16(p);
 | |
|     p += sizeof(uint16_t);
 | |
|     if (!str_len)
 | |
|         return NULL;
 | |
| 
 | |
|     /* tag content */
 | |
|     p += str_len;
 | |
|     if (p - attr_cont->buf >= total_length)
 | |
|         return NULL;
 | |
| 
 | |
|     /* attribute num */
 | |
|     attr_num = get_uint16(p);
 | |
|     p += sizeof(uint16_t);
 | |
|     if (p - attr_cont->buf >= total_length)
 | |
|         return NULL;
 | |
| 
 | |
|     if (p_total_length)
 | |
|         *p_total_length = total_length;
 | |
| 
 | |
|     if (p_attr_num)
 | |
|         *p_attr_num = attr_num;
 | |
| 
 | |
|     /* first attribute */
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| static char*
 | |
| attr_container_get_attr_next(const char *curr_attr)
 | |
| {
 | |
|     char *p = (char*) curr_attr;
 | |
|     uint8_t type;
 | |
| 
 | |
|     /* key length and key */
 | |
|     p += sizeof(uint16_t) + get_uint16(p);
 | |
|     type = *p++;
 | |
| 
 | |
|     /* Short type to Boolean type */
 | |
|     if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN) {
 | |
|         p += 1 << (type & 3);
 | |
|         return p;
 | |
|     }
 | |
|     /* String type */
 | |
|     else if (type == ATTR_TYPE_STRING) {
 | |
|         p += sizeof(uint16_t) + get_uint16(p);
 | |
|         return p;
 | |
|     }
 | |
|     /* ByteArray type */
 | |
|     else if (type == ATTR_TYPE_BYTEARRAY) {
 | |
|         p += sizeof(uint32_t) + get_uint32(p);
 | |
|         return p;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static const char*
 | |
| attr_container_find_attr(const attr_container_t *attr_cont, const char *key)
 | |
| {
 | |
|     uint32_t total_length;
 | |
|     uint16_t str_len, attr_num, i;
 | |
|     const char *p = attr_cont->buf;
 | |
| 
 | |
|     if (!key)
 | |
|         return NULL;
 | |
| 
 | |
|     if (!(p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num)))
 | |
|         return NULL;
 | |
| 
 | |
|     for (i = 0; i < attr_num; i++) {
 | |
|         /* key length */
 | |
|         if (!(str_len = get_uint16(p)))
 | |
|             return NULL;
 | |
| 
 | |
|         if (str_len == strlen(key) + 1
 | |
|                 && memcmp(p + sizeof(uint16_t), key, str_len) == 0) {
 | |
|             if (p + sizeof(uint16_t) + str_len - attr_cont->buf >= total_length)
 | |
|                 return NULL;
 | |
|             return p;
 | |
|         }
 | |
| 
 | |
|         if (!(p = attr_container_get_attr_next(p)))
 | |
|             return NULL;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| char*
 | |
| attr_container_get_attr_end(const attr_container_t *attr_cont)
 | |
| {
 | |
|     uint32_t total_length;
 | |
|     uint16_t attr_num, i;
 | |
|     char *p;
 | |
| 
 | |
|     if (!(p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num)))
 | |
|         return NULL;
 | |
| 
 | |
|     for (i = 0; i < attr_num; i++)
 | |
|         if (!(p = attr_container_get_attr_next(p)))
 | |
|             return NULL;
 | |
| 
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| static char*
 | |
| attr_container_get_msg_end(attr_container_t *attr_cont)
 | |
| {
 | |
|     char *p = attr_cont->buf;
 | |
|     return p + get_uint32(p);
 | |
| }
 | |
| 
 | |
| uint16_t attr_container_get_attr_num(const attr_container_t *attr_cont)
 | |
| {
 | |
|     uint16_t str_len;
 | |
|     /* skip total length */
 | |
|     const char *p = attr_cont->buf + sizeof(uint32_t);
 | |
| 
 | |
|     str_len = get_uint16(p);
 | |
|     /* skip tag length and tag */
 | |
|     p += sizeof(uint16_t) + str_len;
 | |
| 
 | |
|     /* attribute num */
 | |
|     return get_uint16(p);
 | |
| }
 | |
| 
 | |
| static void attr_container_inc_attr_num(attr_container_t *attr_cont)
 | |
| {
 | |
|     uint16_t str_len, attr_num;
 | |
|     /* skip total length */
 | |
|     char *p = attr_cont->buf + sizeof(uint32_t);
 | |
| 
 | |
|     str_len = get_uint16(p);
 | |
|     /* skip tag length and tag */
 | |
|     p += sizeof(uint16_t) + str_len;
 | |
| 
 | |
|     /* attribute num */
 | |
|     attr_num = get_uint16(p) + 1;
 | |
|     set_uint16(p, attr_num);
 | |
| }
 | |
| 
 | |
| attr_container_t *
 | |
| attr_container_create(const char *tag)
 | |
| {
 | |
|     attr_container_t *attr_cont;
 | |
|     int length, tag_length;
 | |
|     char *p;
 | |
| 
 | |
|     tag_length = tag ? strlen(tag) + 1 : 1;
 | |
|     length = offsetof(attr_container_t, buf) +
 | |
|     /* total length + tag length + tag + reserved 100 bytes */
 | |
|     sizeof(uint32_t) + sizeof(uint16_t) + tag_length + 100;
 | |
| 
 | |
|     if (!(attr_cont = attr_container_malloc(length))) {
 | |
|         attr_container_printf(
 | |
|                 "Create attr_container failed: allocate memory failed.\r\n");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     memset(attr_cont, 0, length);
 | |
|     p = attr_cont->buf;
 | |
| 
 | |
|     /* total length */
 | |
|     set_uint32(p, length - offsetof(attr_container_t, buf));
 | |
|     p += 4;
 | |
| 
 | |
|     /* tag length, tag */
 | |
|     set_uint16(p, tag_length);
 | |
|     p += 2;
 | |
|     if (tag)
 | |
|         bh_memcpy_s(p, tag_length, tag, tag_length);
 | |
| 
 | |
|     return attr_cont;
 | |
| }
 | |
| 
 | |
| void attr_container_destroy(const attr_container_t *attr_cont)
 | |
| {
 | |
|     if (attr_cont)
 | |
|         attr_container_free((char*) attr_cont);
 | |
| }
 | |
| 
 | |
| static bool check_set_attr(attr_container_t **p_attr_cont, const char *key)
 | |
| {
 | |
|     uint32_t flags;
 | |
| 
 | |
|     if (!p_attr_cont || !*p_attr_cont || !key || strlen(key) == 0) {
 | |
|         attr_container_printf(
 | |
|                 "Set attribute failed: invalid input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     flags = get_uint32((char*) *p_attr_cont);
 | |
|     if (flags & ATTR_CONT_READONLY_SHIFT) {
 | |
|         attr_container_printf(
 | |
|                 "Set attribute failed: attribute container is readonly.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
 | |
|         int type, const void *value, int value_length)
 | |
| {
 | |
|     attr_container_t *attr_cont, *attr_cont1;
 | |
|     uint16_t str_len;
 | |
|     uint32_t total_length, attr_len;
 | |
|     char *p, *p1, *attr_end, *msg_end, *attr_buf;
 | |
| 
 | |
|     if (!check_set_attr(p_attr_cont, key)) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     attr_cont = *p_attr_cont;
 | |
|     p = attr_cont->buf;
 | |
|     total_length = get_uint32(p);
 | |
| 
 | |
|     if (!(attr_end = attr_container_get_attr_end(attr_cont))) {
 | |
|         attr_container_printf("Set attr failed: get attr end failed.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     msg_end = attr_container_get_msg_end(attr_cont);
 | |
| 
 | |
|     /* key len + key + '\0' + type */
 | |
|     attr_len = sizeof(uint16_t) + strlen(key) + 1 + 1;
 | |
|     if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN)
 | |
|         attr_len += 1 << (type & 3);
 | |
|     else if (type == ATTR_TYPE_STRING)
 | |
|         attr_len += sizeof(uint16_t) + value_length;
 | |
|     else if (type == ATTR_TYPE_BYTEARRAY)
 | |
|         attr_len += sizeof(uint32_t) + value_length;
 | |
| 
 | |
|     if (!(p = attr_buf = attr_container_malloc(attr_len))) {
 | |
|         attr_container_printf("Set attr failed: allocate memory failed.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /* Set the attr buf */
 | |
|     str_len = strlen(key) + 1;
 | |
|     set_uint16(p, str_len);
 | |
|     p += sizeof(uint16_t);
 | |
|     bh_memcpy_s(p, str_len, key, str_len);
 | |
|     p += str_len;
 | |
| 
 | |
|     *p++ = type;
 | |
|     if (type >= ATTR_TYPE_SHORT && type <= ATTR_TYPE_BOOLEAN)
 | |
|         bh_memcpy_s(p, 1 << (type & 3), value, 1 << (type & 3));
 | |
|     else if (type == ATTR_TYPE_STRING) {
 | |
|         set_uint16(p, value_length);
 | |
|         p += sizeof(uint16_t);
 | |
|         bh_memcpy_s(p, value_length, value, value_length);
 | |
|     } else if (type == ATTR_TYPE_BYTEARRAY) {
 | |
|         set_uint32(p, value_length);
 | |
|         p += sizeof(uint32_t);
 | |
|         bh_memcpy_s(p, value_length, value, value_length);
 | |
|     }
 | |
| 
 | |
|     if ((p = (char*) attr_container_find_attr(attr_cont, key))) {
 | |
|         /* key found */
 | |
|         p1 = attr_container_get_attr_next(p);
 | |
| 
 | |
|         if (p1 - p == attr_len) {
 | |
|             bh_memcpy_s(p, attr_len, attr_buf, attr_len);
 | |
|             attr_container_free(attr_buf);
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         if (p1 - p + msg_end - attr_end >= attr_len) {
 | |
|             memmove(p, p1, attr_end - p1);
 | |
|             bh_memcpy_s(p + (attr_end - p1), attr_len, attr_buf, attr_len);
 | |
|             attr_container_free(attr_buf);
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         total_length += attr_len + 100;
 | |
|         if (!(attr_cont1 = attr_container_malloc(
 | |
|                 offsetof(attr_container_t, buf) + total_length))) {
 | |
|             attr_container_printf(
 | |
|                     "Set attr failed: allocate memory failed.\r\n");
 | |
|             attr_container_free(attr_buf);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bh_memcpy_s(attr_cont1, p - (char* )attr_cont, attr_cont,
 | |
|                 p - (char* )attr_cont);
 | |
|         bh_memcpy_s((char* )attr_cont1 + (unsigned )(p - (char* )attr_cont),
 | |
|                 attr_end - p1, p1, attr_end - p1);
 | |
|         bh_memcpy_s(
 | |
|                 (char* )attr_cont1 + (unsigned )(p - (char* )attr_cont)
 | |
|                         + (unsigned )(attr_end - p1), attr_len, attr_buf,
 | |
|                 attr_len);
 | |
|         p = attr_cont1->buf;
 | |
|         set_uint32(p, total_length);
 | |
|         *p_attr_cont = attr_cont1;
 | |
|         /* Free original buffer */
 | |
|         attr_container_free(attr_cont);
 | |
|         attr_container_free(attr_buf);
 | |
|         return true;
 | |
|     } else {
 | |
|         /* key not found */
 | |
|         if (msg_end - attr_end >= attr_len) {
 | |
|             bh_memcpy_s(attr_end, msg_end - attr_end, attr_buf, attr_len);
 | |
|             attr_container_inc_attr_num(attr_cont);
 | |
|             attr_container_free(attr_buf);
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         total_length += attr_len + 100;
 | |
|         if (!(attr_cont1 = attr_container_malloc(
 | |
|                 offsetof(attr_container_t, buf) + total_length))) {
 | |
|             attr_container_printf(
 | |
|                     "Set attr failed: allocate memory failed.\r\n");
 | |
|             attr_container_free(attr_buf);
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         bh_memcpy_s(attr_cont1, attr_end - (char* )attr_cont, attr_cont,
 | |
|                 attr_end - (char* )attr_cont);
 | |
|         bh_memcpy_s(
 | |
|                 (char* )attr_cont1 + (unsigned )(attr_end - (char* )attr_cont),
 | |
|                 attr_len, attr_buf, attr_len);
 | |
|         attr_container_inc_attr_num(attr_cont1);
 | |
|         p = attr_cont1->buf;
 | |
|         set_uint32(p, total_length);
 | |
|         *p_attr_cont = attr_cont1;
 | |
|         /* Free original buffer */
 | |
|         attr_container_free(attr_cont);
 | |
|         attr_container_free(attr_buf);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool attr_container_set_short(attr_container_t **p_attr_cont, const char *key,
 | |
|         short value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_SHORT, &value, 2);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_int(attr_container_t **p_attr_cont, const char *key,
 | |
|         int value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT, &value, 4);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_int64(attr_container_t **p_attr_cont, const char *key,
 | |
|         int64_t value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_INT64, &value, 8);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_byte(attr_container_t **p_attr_cont, const char *key,
 | |
|         int8_t value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTE, &value, 1);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_uint16(attr_container_t **p_attr_cont, const char *key,
 | |
|         uint16_t value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_UINT16, &value,
 | |
|             2);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_float(attr_container_t **p_attr_cont, const char *key,
 | |
|         float value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_FLOAT, &value, 4);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_double(attr_container_t **p_attr_cont, const char *key,
 | |
|         double value)
 | |
| {
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_DOUBLE, &value,
 | |
|             8);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_bool(attr_container_t **p_attr_cont, const char *key,
 | |
|         bool value)
 | |
| {
 | |
|     int8_t value1 = value ? 1 : 0;
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BOOLEAN, &value1,
 | |
|             1);
 | |
| }
 | |
| 
 | |
| bool attr_container_set_string(attr_container_t **p_attr_cont, const char *key,
 | |
|         const char *value)
 | |
| {
 | |
|     if (!value) {
 | |
|         attr_container_printf("Set attr failed: invald input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_STRING, value,
 | |
|             strlen(value) + 1);;
 | |
| }
 | |
| 
 | |
| bool attr_container_set_bytearray(attr_container_t **p_attr_cont,
 | |
|         const char *key, const int8_t *value, unsigned length)
 | |
| {
 | |
|     if (!value) {
 | |
|         attr_container_printf("Set attr failed: invald input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
|     return attr_container_set_attr(p_attr_cont, key, ATTR_TYPE_BYTEARRAY, value,
 | |
|             length);;
 | |
| }
 | |
| 
 | |
| static const char*
 | |
| attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
 | |
| {
 | |
|     const char *attr_addr;
 | |
| 
 | |
|     if (!attr_cont || !key) {
 | |
|         attr_container_printf(
 | |
|                 "Get attribute failed: invalid input arguments.\r\n");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     if (!(attr_addr = attr_container_find_attr(attr_cont, key))) {
 | |
|         attr_container_printf("Get attribute failed: lookup key failed.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /* key len + key + '\0' */
 | |
|     return attr_addr + 2 + strlen(key) + 1;
 | |
| }
 | |
| 
 | |
| #define TEMPLATE_ATTR_BUF_TO_VALUE(attr, key, var_name) do {\
 | |
|     jvalue val;                                             \
 | |
|     const char *addr = attr_container_get_attr(attr, key);  \
 | |
|     uint8_t type;                                           \
 | |
|     if (!addr)                                              \
 | |
|       return 0;                                             \
 | |
|     val.j = 0;                                              \
 | |
|     type = *(uint8_t*)addr++;                               \
 | |
|     switch (type) {                                         \
 | |
|       case ATTR_TYPE_SHORT:                                 \
 | |
|       case ATTR_TYPE_INT:                                   \
 | |
|       case ATTR_TYPE_INT64:                                 \
 | |
|       case ATTR_TYPE_BYTE:                                  \
 | |
|       case ATTR_TYPE_UINT16:                                \
 | |
|       case ATTR_TYPE_FLOAT:                                 \
 | |
|       case ATTR_TYPE_DOUBLE:                                \
 | |
|       case ATTR_TYPE_BOOLEAN:                               \
 | |
|         bh_memcpy_s(&val, sizeof(val.var_name), addr, 1 << (type & 3)); \
 | |
|         break;                                              \
 | |
|       case ATTR_TYPE_STRING:                                \
 | |
|       {                                                     \
 | |
|         unsigned len= get_uint16(addr);                     \
 | |
|         addr += 2;                                          \
 | |
|         if (len > sizeof(val.var_name))                     \
 | |
|           len = sizeof(val.var_name);                       \
 | |
|         bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
 | |
|         break;                                              \
 | |
|       }                                                     \
 | |
|       case ATTR_TYPE_BYTEARRAY:                             \
 | |
|       {                                                     \
 | |
|         unsigned len= get_uint32(addr);                     \
 | |
|         addr += 4;                                          \
 | |
|         if (len > sizeof(val.var_name))                     \
 | |
|           len = sizeof(val.var_name);                       \
 | |
|         bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
 | |
|         break;                                              \
 | |
|       }                                                     \
 | |
|     }                                                       \
 | |
|     return val.var_name;                                    \
 | |
|   } while (0)
 | |
| 
 | |
| short attr_container_get_as_short(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s);
 | |
| }
 | |
| 
 | |
| int attr_container_get_as_int(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, i);
 | |
| }
 | |
| 
 | |
| int64_t attr_container_get_as_int64(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, j);
 | |
| }
 | |
| 
 | |
| int8_t attr_container_get_as_byte(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, b);
 | |
| }
 | |
| 
 | |
| uint16_t attr_container_get_as_uint16(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, s);
 | |
| }
 | |
| 
 | |
| float attr_container_get_as_float(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, f);
 | |
| }
 | |
| 
 | |
| double attr_container_get_as_double(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, d);
 | |
| }
 | |
| 
 | |
| bool attr_container_get_as_bool(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     TEMPLATE_ATTR_BUF_TO_VALUE(attr_cont, key, z);
 | |
| }
 | |
| 
 | |
| const int8_t*
 | |
| attr_container_get_as_bytearray(const attr_container_t *attr_cont,
 | |
|         const char *key, unsigned *array_length)
 | |
| {
 | |
|     const char *addr = attr_container_get_attr(attr_cont, key);
 | |
|     uint8_t type;
 | |
|     uint32_t length;
 | |
| 
 | |
|     if (!addr)
 | |
|         return NULL;
 | |
| 
 | |
|     if (!array_length) {
 | |
|         attr_container_printf("Get attribute failed: invalid input arguments.");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     type = *(uint8_t*) addr++;
 | |
|     switch (type) {
 | |
|     case ATTR_TYPE_SHORT:
 | |
|     case ATTR_TYPE_INT:
 | |
|     case ATTR_TYPE_INT64:
 | |
|     case ATTR_TYPE_BYTE:
 | |
|     case ATTR_TYPE_UINT16:
 | |
|     case ATTR_TYPE_FLOAT:
 | |
|     case ATTR_TYPE_DOUBLE:
 | |
|     case ATTR_TYPE_BOOLEAN:
 | |
|         length = 1 << (type & 3);
 | |
|         break;
 | |
|     case ATTR_TYPE_STRING:
 | |
|         length = get_uint16(addr);
 | |
|         addr += 2;
 | |
|         break;
 | |
|     case ATTR_TYPE_BYTEARRAY:
 | |
|         length = get_uint32(addr);
 | |
|         addr += 4;
 | |
|         break;
 | |
|     default:
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     *array_length = length;
 | |
|     return (const int8_t*) addr;
 | |
| }
 | |
| 
 | |
| char*
 | |
| attr_container_get_as_string(const attr_container_t *attr_cont, const char *key)
 | |
| {
 | |
|     unsigned array_length;
 | |
|     return (char*) attr_container_get_as_bytearray(attr_cont, key,
 | |
|             &array_length);
 | |
| }
 | |
| 
 | |
| const char*
 | |
| attr_container_get_tag(const attr_container_t *attr_cont)
 | |
| {
 | |
|     return attr_cont ?
 | |
|             attr_cont->buf + sizeof(uint32_t) + sizeof(uint16_t) : NULL;
 | |
| }
 | |
| 
 | |
| bool attr_container_contain_key(const attr_container_t *attr_cont,
 | |
|         const char *key)
 | |
| {
 | |
|     if (!attr_cont || !key || !strlen(key)) {
 | |
|         attr_container_printf(
 | |
|                 "Check contain key failed: invalid input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
|     return attr_container_find_attr(attr_cont, key) ? true : false;
 | |
| }
 | |
| 
 | |
| unsigned int attr_container_get_serialize_length(
 | |
|         const attr_container_t *attr_cont)
 | |
| {
 | |
|     const char *p;
 | |
| 
 | |
|     if (!attr_cont) {
 | |
|         attr_container_printf(
 | |
|                 "Get container serialize length failed: invalid input arguments.\r\n");
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     p = attr_cont->buf;
 | |
|     return sizeof(uint16_t) + get_uint32(p);
 | |
| }
 | |
| 
 | |
| bool attr_container_serialize(char *buf, const attr_container_t *attr_cont)
 | |
| {
 | |
|     const char *p;
 | |
|     uint16_t flags;
 | |
|     uint32_t length;
 | |
| 
 | |
|     if (!buf || !attr_cont) {
 | |
|         attr_container_printf(
 | |
|                 "Container serialize failed: invalid input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     p = attr_cont->buf;
 | |
|     length = sizeof(uint16_t) + get_uint32(p);
 | |
|     bh_memcpy_s(buf, length, attr_cont, length);
 | |
|     /* Set readonly */
 | |
|     flags = get_uint16((const char*) attr_cont);
 | |
|     set_uint16(buf, flags | (1 << ATTR_CONT_READONLY_SHIFT));
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool attr_container_is_constant(const attr_container_t* attr_cont)
 | |
| {
 | |
|     uint16_t flags;
 | |
| 
 | |
|     if (!attr_cont) {
 | |
|         attr_container_printf(
 | |
|                 "Container check const: invalid input arguments.\r\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     flags = get_uint16((const char*) attr_cont);
 | |
|     return (flags & (1 << ATTR_CONT_READONLY_SHIFT)) ? true : false;
 | |
| }
 | |
| 
 | |
| void attr_container_dump(const attr_container_t *attr_cont)
 | |
| {
 | |
|     uint32_t total_length;
 | |
|     uint16_t attr_num, i, type;
 | |
|     const char *p, *tag, *key;
 | |
|     jvalue value;
 | |
| 
 | |
|     if (!attr_cont)
 | |
|         return;
 | |
| 
 | |
|     tag = attr_container_get_tag(attr_cont);
 | |
|     if (!tag)
 | |
|         return;
 | |
| 
 | |
|     attr_container_printf("Attribute container dump:\n");
 | |
|     attr_container_printf("Tag: %s\n", tag);
 | |
| 
 | |
|     p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num);
 | |
|     if (!p)
 | |
|         return;
 | |
| 
 | |
|     attr_container_printf("Attribute list:\n");
 | |
|     for (i = 0; i < attr_num; i++) {
 | |
|         key = p + 2;
 | |
|         /* Skip key len and key */
 | |
|         p += 2 + get_uint16(p);
 | |
|         type = *p++;
 | |
|         attr_container_printf("  key: %s", key);
 | |
| 
 | |
|         switch (type) {
 | |
|         case ATTR_TYPE_SHORT:
 | |
|             bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t));
 | |
|             attr_container_printf(", type: short, value: 0x%x\n",
 | |
|                     value.s & 0xFFFF);
 | |
|             p += 2;
 | |
|             break;
 | |
|         case ATTR_TYPE_INT:
 | |
|             bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t));
 | |
|             attr_container_printf(", type: int, value: 0x%x\n", value.i);
 | |
|             p += 4;
 | |
|             break;
 | |
|         case ATTR_TYPE_INT64:
 | |
|             bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t));
 | |
|             attr_container_printf(", type: int64, value: 0x%llx\n", (long long unsigned int)(value.j));
 | |
|             p += 8;
 | |
|             break;
 | |
|         case ATTR_TYPE_BYTE:
 | |
|             bh_memcpy_s(&value.b, 1, p, 1);
 | |
|             attr_container_printf(", type: byte, value: 0x%x\n",
 | |
|                     value.b & 0xFF);
 | |
|             p++;
 | |
|             break;
 | |
|         case ATTR_TYPE_UINT16:
 | |
|             bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t));
 | |
|             attr_container_printf(", type: uint16, value: 0x%x\n", value.c);
 | |
|             p += 2;
 | |
|             break;
 | |
|         case ATTR_TYPE_FLOAT:
 | |
|             bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
 | |
|             attr_container_printf(", type: float, value: %f\n", value.f);
 | |
|             p += 4;
 | |
|             break;
 | |
|         case ATTR_TYPE_DOUBLE:
 | |
|             bh_memcpy_s(&value.d, sizeof(double), p, sizeof(double));
 | |
|             attr_container_printf(", type: double, value: %f\n", value.d);
 | |
|             p += 8;
 | |
|             break;
 | |
|         case ATTR_TYPE_BOOLEAN:
 | |
|             bh_memcpy_s(&value.z, 1, p, 1);
 | |
|             attr_container_printf(", type: bool, value: 0x%x\n", value.z);
 | |
|             p++;
 | |
|             break;
 | |
|         case ATTR_TYPE_STRING:
 | |
|             attr_container_printf(", type: string, value: %s\n",
 | |
|                     p + sizeof(uint16_t));
 | |
|             p += sizeof(uint16_t) + get_uint16(p);
 | |
|             break;
 | |
|         case ATTR_TYPE_BYTEARRAY:
 | |
|             attr_container_printf(", type: byte array, length: %d\n",
 | |
|                     get_uint32(p));
 | |
|             p += sizeof(uint32_t) + get_uint32(p);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     attr_container_printf("\n");
 | |
| }
 | |
| 
 |