Skip to content

Commit ce4eba5

Browse files
SanjayyyVcfriedt
authored andcommitted
lib: utils: json: add support for mixed array types
Added support for mixed array types in JSON by introducing a new type - json_mixed_arr_descr. Added APIs for mixed array type parsing and encoding. Signed-off-by: Sanjay Vallimanalan <[email protected]>
1 parent 6c37aa9 commit ce4eba5

File tree

1 file changed

+373
-0
lines changed

1 file changed

+373
-0
lines changed

lib/utils/json.c

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,10 @@ static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
780780
return type2 == JSON_TOK_TRUE || type2 == JSON_TOK_FALSE;
781781
}
782782

783+
if (type1 == JSON_TOK_ARRAY_START && type2 == JSON_TOK_MIXED_ARRAY) {
784+
return true;
785+
}
786+
783787
if (type1 == JSON_TOK_NUMBER && type2 == JSON_TOK_FLOAT) {
784788
return true;
785789
}
@@ -816,6 +820,12 @@ static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
816820
return true;
817821
}
818822

823+
if (type2 == JSON_TOK_ENCODED_OBJ) {
824+
return (type1 == JSON_TOK_OBJECT_START ||
825+
type1 == JSON_TOK_ARRAY_START ||
826+
type1 == JSON_TOK_STRING);
827+
}
828+
819829
if (type1 == JSON_TOK_ARRAY_START && type2 == JSON_TOK_OBJ_ARRAY) {
820830
return true;
821831
}
@@ -1781,3 +1791,366 @@ ssize_t json_calc_encoded_arr_len(const struct json_obj_descr *descr,
17811791

17821792
return total;
17831793
}
1794+
1795+
1796+
static int mixed_arr_parse(struct json_obj *arr,
1797+
const struct json_mixed_arr_descr *descr,
1798+
size_t descr_len, void *val);
1799+
int json_mixed_arr_encode(const struct json_mixed_arr_descr *descr,
1800+
size_t descr_len, void *val,
1801+
json_append_bytes_t append_bytes,
1802+
void *data);
1803+
1804+
static int extract_raw_json_data(struct json_obj *obj, struct json_token *value,
1805+
char **field_ptr)
1806+
{
1807+
char *start_pos = value->start;
1808+
1809+
switch (value->type) {
1810+
case JSON_TOK_OBJECT_START:
1811+
case JSON_TOK_ARRAY_START: {
1812+
struct json_obj_key_value kv = {
1813+
.key = NULL,
1814+
.key_len = 0,
1815+
.value = *value
1816+
};
1817+
1818+
int ret = skip_field(obj, &kv);
1819+
1820+
if (ret < 0) {
1821+
return ret;
1822+
}
1823+
1824+
char *end_pos = obj->lex.pos;
1825+
*end_pos = '\0';
1826+
*field_ptr = start_pos;
1827+
1828+
return 0;
1829+
}
1830+
1831+
case JSON_TOK_STRING:
1832+
*value->end = '\0';
1833+
*field_ptr = start_pos;
1834+
return 0;
1835+
1836+
default:
1837+
return -EINVAL;
1838+
}
1839+
}
1840+
1841+
static int64_t decode_mixed_value(struct json_obj *obj,
1842+
const struct json_mixed_arr_descr *elem,
1843+
struct json_token *value,
1844+
void *field, void *val)
1845+
{
1846+
if (!equivalent_types(value->type, elem->type)) {
1847+
return -EINVAL;
1848+
}
1849+
1850+
switch (elem->type) {
1851+
case JSON_TOK_OBJECT_START: {
1852+
return obj_parse(obj, elem->object.sub_descr,
1853+
elem->object.sub_descr_len, field);
1854+
}
1855+
case JSON_TOK_ARRAY_START: {
1856+
const struct json_obj_descr *actual_elem_descr = elem->array.element_descr;
1857+
size_t actual_n_elements = elem->array.n_elements;
1858+
1859+
if (actual_elem_descr->type == JSON_TOK_ARRAY_START) {
1860+
actual_elem_descr = actual_elem_descr->array.element_descr;
1861+
}
1862+
return arr_parse(obj, actual_elem_descr, actual_n_elements, field, val);
1863+
}
1864+
case JSON_TOK_MIXED_ARRAY: {
1865+
return mixed_arr_parse(obj, elem->mixed_array.sub_descr,
1866+
elem->mixed_array.sub_descr_len,
1867+
field);
1868+
}
1869+
case JSON_TOK_FALSE:
1870+
case JSON_TOK_TRUE: {
1871+
bool *v = field;
1872+
1873+
*v = (value->type == JSON_TOK_TRUE);
1874+
return 0;
1875+
}
1876+
case JSON_TOK_NUMBER: {
1877+
int32_t *num32 = field;
1878+
1879+
return decode_int32(value, num32);
1880+
}
1881+
case JSON_TOK_INT: {
1882+
return decode_int(value, field, elem->primitive.size);
1883+
}
1884+
case JSON_TOK_UINT: {
1885+
return decode_uint(value, field, elem->primitive.size);
1886+
}
1887+
case JSON_TOK_INT64: {
1888+
int64_t *num64 = field;
1889+
1890+
return decode_int64(value, num64);
1891+
}
1892+
case JSON_TOK_UINT64: {
1893+
uint64_t *unum64 = field;
1894+
1895+
return decode_uint64(value, unum64);
1896+
}
1897+
case JSON_TOK_FLOAT_FP: {
1898+
float *f_num = field;
1899+
1900+
return decode_float(value, f_num);
1901+
}
1902+
case JSON_TOK_DOUBLE_FP: {
1903+
double *d_num = field;
1904+
1905+
return decode_double(value, d_num);
1906+
}
1907+
case JSON_TOK_STRING: {
1908+
char **str_ptr = field;
1909+
1910+
*value->end = '\0';
1911+
*str_ptr = value->start;
1912+
return 0;
1913+
}
1914+
case JSON_TOK_STRING_BUF: {
1915+
char *str_buf = field;
1916+
1917+
return decode_string_buf(value, str_buf, elem->primitive.size);
1918+
}
1919+
case JSON_TOK_OBJ_ARRAY: {
1920+
struct json_obj_token *obj_token = field;
1921+
1922+
obj_token->start = value->start;
1923+
return arr_data_parse(obj, obj_token);
1924+
}
1925+
case JSON_TOK_OPAQUE:
1926+
case JSON_TOK_FLOAT: {
1927+
struct json_obj_token *obj_token = field;
1928+
1929+
obj_token->start = value->start;
1930+
obj_token->length = value->end - value->start;
1931+
return 0;
1932+
}
1933+
case JSON_TOK_ENCODED_OBJ: {
1934+
char **str_ptr = field;
1935+
1936+
return extract_raw_json_data(obj, value, str_ptr);
1937+
}
1938+
case JSON_TOK_NULL: {
1939+
memset(field, 0, elem->primitive.size);
1940+
return 0;
1941+
}
1942+
default:
1943+
return -EINVAL;
1944+
}
1945+
}
1946+
1947+
static int encode_mixed_value(const struct json_mixed_arr_descr *elem,
1948+
void *field, void *val,
1949+
json_append_bytes_t append_bytes, void *data)
1950+
{
1951+
1952+
switch (elem->type) {
1953+
case JSON_TOK_OBJECT_START: {
1954+
return json_obj_encode(elem->object.sub_descr,
1955+
elem->object.sub_descr_len,
1956+
field, append_bytes, data);
1957+
}
1958+
case JSON_TOK_ARRAY_START: {
1959+
const struct json_obj_descr *actual_elem_descr = elem->array.element_descr;
1960+
1961+
if (actual_elem_descr->type == JSON_TOK_ARRAY_START) {
1962+
actual_elem_descr = actual_elem_descr->array.element_descr;
1963+
}
1964+
return arr_encode(actual_elem_descr, field, val, append_bytes, data);
1965+
}
1966+
case JSON_TOK_MIXED_ARRAY: {
1967+
return json_mixed_arr_encode(elem->mixed_array.sub_descr,
1968+
elem->mixed_array.sub_descr_len,
1969+
field, append_bytes, data);
1970+
}
1971+
case JSON_TOK_FALSE:
1972+
case JSON_TOK_TRUE: {
1973+
return bool_encode(field, append_bytes, data);
1974+
}
1975+
case JSON_TOK_STRING: {
1976+
return str_encode(*((char **)field), append_bytes, data);
1977+
}
1978+
case JSON_TOK_STRING_BUF: {
1979+
return str_encode(field, append_bytes, data);
1980+
}
1981+
case JSON_TOK_NUMBER: {
1982+
return int32_encode(field, append_bytes, data);
1983+
}
1984+
case JSON_TOK_INT: {
1985+
return int_encode(field, elem->primitive.size, append_bytes, data);
1986+
}
1987+
case JSON_TOK_UINT: {
1988+
return uint_encode(field, elem->primitive.size, append_bytes, data);
1989+
}
1990+
case JSON_TOK_INT64: {
1991+
return int64_encode(field, append_bytes, data);
1992+
}
1993+
case JSON_TOK_UINT64: {
1994+
return uint64_encode(field, append_bytes, data);
1995+
}
1996+
case JSON_TOK_FLOAT_FP: {
1997+
return float_encode(field, append_bytes, data);
1998+
}
1999+
case JSON_TOK_DOUBLE_FP: {
2000+
return double_encode(field, append_bytes, data);
2001+
}
2002+
case JSON_TOK_FLOAT: {
2003+
return float_ascii_encode(field, append_bytes, data);
2004+
}
2005+
case JSON_TOK_OPAQUE: {
2006+
return opaque_string_encode(field, append_bytes, data);
2007+
}
2008+
case JSON_TOK_ENCODED_OBJ: {
2009+
return encoded_obj_encode((const char **)field, append_bytes, data);
2010+
}
2011+
default:
2012+
return -EINVAL;
2013+
}
2014+
}
2015+
2016+
static int mixed_arr_parse(struct json_obj *arr,
2017+
const struct json_mixed_arr_descr *descr,
2018+
size_t descr_len, void *val)
2019+
{
2020+
struct json_token tok;
2021+
size_t elem_idx = 0;
2022+
void *field_ptr;
2023+
int ret;
2024+
2025+
if (descr_len == 0) {
2026+
if (!arr_next(arr, &tok) && tok.type == JSON_TOK_ARRAY_END) {
2027+
return 0;
2028+
}
2029+
return -EINVAL;
2030+
}
2031+
2032+
while (!arr_next(arr, &tok)) {
2033+
if (tok.type == JSON_TOK_ARRAY_END) {
2034+
return elem_idx;
2035+
}
2036+
2037+
if (elem_idx >= descr_len) {
2038+
return -ENOSPC;
2039+
}
2040+
2041+
switch (descr[elem_idx].type) {
2042+
case JSON_TOK_OBJECT_START:
2043+
field_ptr = (char *)val + descr[elem_idx].object.offset;
2044+
break;
2045+
case JSON_TOK_ARRAY_START:
2046+
field_ptr = (char *)val + descr[elem_idx].array.offset;
2047+
break;
2048+
case JSON_TOK_MIXED_ARRAY:
2049+
field_ptr = (char *)val + descr[elem_idx].mixed_array.offset;
2050+
break;
2051+
default:
2052+
field_ptr = (char *)val + descr[elem_idx].primitive.offset;
2053+
break;
2054+
}
2055+
2056+
ret = decode_mixed_value(arr, &descr[elem_idx], &tok, field_ptr, val);
2057+
if (ret < 0) {
2058+
return ret;
2059+
}
2060+
2061+
elem_idx++;
2062+
}
2063+
2064+
return elem_idx;
2065+
}
2066+
2067+
int json_mixed_arr_parse(char *json, size_t len,
2068+
const struct json_mixed_arr_descr *descr,
2069+
size_t descr_len, void *val)
2070+
{
2071+
struct json_obj arr;
2072+
int ret;
2073+
2074+
ret = arr_init(&arr, json, len);
2075+
if (ret < 0) {
2076+
return ret;
2077+
}
2078+
2079+
return mixed_arr_parse(&arr, descr, descr_len, val);
2080+
}
2081+
2082+
int json_mixed_arr_encode(const struct json_mixed_arr_descr *descr,
2083+
size_t descr_len, void *val,
2084+
json_append_bytes_t append_bytes,
2085+
void *data)
2086+
{
2087+
size_t *element_count;
2088+
size_t i;
2089+
int ret;
2090+
void *field_ptr;
2091+
2092+
if (descr_len == 0) {
2093+
return append_bytes("[]", 2, data);
2094+
}
2095+
2096+
element_count = (size_t *)((char *)val + descr[0].count_offset);
2097+
2098+
ret = append_bytes("[", 1, data);
2099+
if (ret < 0) {
2100+
return ret;
2101+
}
2102+
2103+
for (i = 0; i < *element_count && i < descr_len; i++) {
2104+
switch (descr[i].type) {
2105+
case JSON_TOK_OBJECT_START:
2106+
field_ptr = (char *)val + descr[i].object.offset;
2107+
break;
2108+
case JSON_TOK_ARRAY_START:
2109+
field_ptr = (char *)val + descr[i].array.offset;
2110+
break;
2111+
case JSON_TOK_MIXED_ARRAY:
2112+
field_ptr = (char *)val + descr[i].mixed_array.offset;
2113+
break;
2114+
default:
2115+
field_ptr = (char *)val + descr[i].primitive.offset;
2116+
break;
2117+
}
2118+
2119+
ret = encode_mixed_value(&descr[i], field_ptr, val, append_bytes, data);
2120+
if (ret < 0) {
2121+
return ret;
2122+
}
2123+
2124+
if (i < *element_count - 1) {
2125+
ret = append_bytes(",", 1, data);
2126+
if (ret < 0) {
2127+
return ret;
2128+
}
2129+
}
2130+
}
2131+
2132+
return append_bytes("]", 1, data);
2133+
}
2134+
2135+
int json_mixed_arr_encode_buf(const struct json_mixed_arr_descr *descr,
2136+
size_t descr_len, void *val,
2137+
char *buffer, size_t buf_size)
2138+
{
2139+
struct appender appender = { .buffer = buffer, .size = buf_size };
2140+
2141+
return json_mixed_arr_encode(descr, descr_len, val, append_bytes_to_buf, &appender);
2142+
}
2143+
2144+
ssize_t json_calc_mixed_arr_len(const struct json_mixed_arr_descr *descr,
2145+
size_t descr_len, void *val)
2146+
{
2147+
ssize_t total = 0;
2148+
int ret;
2149+
2150+
ret = json_mixed_arr_encode(descr, descr_len, val, measure_bytes, &total);
2151+
if (ret < 0) {
2152+
return ret;
2153+
}
2154+
2155+
return total;
2156+
}

0 commit comments

Comments
 (0)