1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include <libwebsockets.h> 26d4afb5ceSopenharmony_ci#include <private-lib-core.h> 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#include <assert.h> 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_cisigned char 31d4afb5ceSopenharmony_cilws_struct_schema_only_lejp_cb(struct lejp_ctx *ctx, char reason) 32d4afb5ceSopenharmony_ci{ 33d4afb5ceSopenharmony_ci lws_struct_args_t *a = (lws_struct_args_t *)ctx->user; 34d4afb5ceSopenharmony_ci const lws_struct_map_t *map = a->map_st[ctx->pst_sp]; 35d4afb5ceSopenharmony_ci size_t n = a->map_entries_st[ctx->pst_sp], imp = 0; 36d4afb5ceSopenharmony_ci lejp_callback cb = map->lejp_cb; 37d4afb5ceSopenharmony_ci 38d4afb5ceSopenharmony_ci if (reason == LEJPCB_PAIR_NAME && strcmp(ctx->path, "schema")) { 39d4afb5ceSopenharmony_ci /* 40d4afb5ceSopenharmony_ci * If not "schema", the schema is implicit rather than 41d4afb5ceSopenharmony_ci * explicitly given, ie, he just goes ahead and starts using 42d4afb5ceSopenharmony_ci * member names that imply a particular type. For example, he 43d4afb5ceSopenharmony_ci * may have an implicit type normally, and a different one for 44d4afb5ceSopenharmony_ci * exceptions that just starts using "error-message" or whatever 45d4afb5ceSopenharmony_ci * and we can understand that's the exception type now. 46d4afb5ceSopenharmony_ci * 47d4afb5ceSopenharmony_ci * Let's look into each of the maps in the top level array 48d4afb5ceSopenharmony_ci * and match the first one that mentions the name he gave here, 49d4afb5ceSopenharmony_ci * and bind to the associated type / create a toplevel object 50d4afb5ceSopenharmony_ci * of that type. 51d4afb5ceSopenharmony_ci */ 52d4afb5ceSopenharmony_ci 53d4afb5ceSopenharmony_ci while (n--) { 54d4afb5ceSopenharmony_ci int m, child_members = (int)map->child_map_size; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci for (m = 0; m < child_members; m++) { 57d4afb5ceSopenharmony_ci const lws_struct_map_t *child = &map->child_map[m]; 58d4afb5ceSopenharmony_ci if (!strcmp(ctx->path, child->colname)) { 59d4afb5ceSopenharmony_ci /* 60d4afb5ceSopenharmony_ci * We matched on him... map is pointing 61d4afb5ceSopenharmony_ci * to the right toplevel type, let's 62d4afb5ceSopenharmony_ci * just pick up from there as if we 63d4afb5ceSopenharmony_ci * matched the explicit schema name... 64d4afb5ceSopenharmony_ci */ 65d4afb5ceSopenharmony_ci ctx->path_match = 1; 66d4afb5ceSopenharmony_ci imp = 1; 67d4afb5ceSopenharmony_ci goto matched; 68d4afb5ceSopenharmony_ci } 69d4afb5ceSopenharmony_ci } 70d4afb5ceSopenharmony_ci map++; 71d4afb5ceSopenharmony_ci } 72d4afb5ceSopenharmony_ci lwsl_notice("%s: can't match implicit schema %s\n", 73d4afb5ceSopenharmony_ci __func__, ctx->path); 74d4afb5ceSopenharmony_ci 75d4afb5ceSopenharmony_ci return -1; 76d4afb5ceSopenharmony_ci } 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci if (reason != LEJPCB_VAL_STR_END || ctx->path_match != 1) 79d4afb5ceSopenharmony_ci return 0; 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci /* If "schema", then look for a matching name in the map array */ 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci while (n--) { 84d4afb5ceSopenharmony_ci if (strcmp(ctx->buf, map->colname)) { 85d4afb5ceSopenharmony_ci map++; 86d4afb5ceSopenharmony_ci continue; 87d4afb5ceSopenharmony_ci } 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_cimatched: 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci a->dest = lwsac_use_zero(&a->ac, map->aux, a->ac_block_size); 92d4afb5ceSopenharmony_ci if (!a->dest) { 93d4afb5ceSopenharmony_ci lwsl_err("%s: OOT\n", __func__); 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci return 1; 96d4afb5ceSopenharmony_ci } 97d4afb5ceSopenharmony_ci a->dest_len = map->aux; 98d4afb5ceSopenharmony_ci if (!ctx->pst_sp) 99d4afb5ceSopenharmony_ci a->top_schema_index = (int)(map - a->map_st[ctx->pst_sp]); 100d4afb5ceSopenharmony_ci 101d4afb5ceSopenharmony_ci if (!cb) 102d4afb5ceSopenharmony_ci cb = lws_struct_default_lejp_cb; 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci lejp_parser_push(ctx, a->dest, &map->child_map[0].colname, 105d4afb5ceSopenharmony_ci (uint8_t)map->child_map_size, cb); 106d4afb5ceSopenharmony_ci a->map_st[ctx->pst_sp] = map->child_map; 107d4afb5ceSopenharmony_ci a->map_entries_st[ctx->pst_sp] = map->child_map_size; 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci // lwsl_notice("%s: child map ofs_clist %d\n", __func__, 110d4afb5ceSopenharmony_ci // (int)a->map_st[ctx->pst_sp]->ofs_clist); 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci if (imp) 113d4afb5ceSopenharmony_ci return cb(ctx, reason); 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci return 0; 116d4afb5ceSopenharmony_ci } 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci lwsl_notice("%s: unknown schema %s\n", __func__, ctx->buf); 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci return 1; 121d4afb5ceSopenharmony_ci} 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_cistatic int 124d4afb5ceSopenharmony_cilws_struct_lejp_push(struct lejp_ctx *ctx, lws_struct_args_t *args, 125d4afb5ceSopenharmony_ci const lws_struct_map_t *map, uint8_t *ch) 126d4afb5ceSopenharmony_ci{ 127d4afb5ceSopenharmony_ci lejp_callback cb = map->lejp_cb; 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci if (!cb) 130d4afb5ceSopenharmony_ci cb = lws_struct_default_lejp_cb; 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci lejp_parser_push(ctx, ch, (const char * const*)map->child_map, 133d4afb5ceSopenharmony_ci (uint8_t)map->child_map_size, cb); 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ci args->map_st[ctx->pst_sp] = map->child_map; 136d4afb5ceSopenharmony_ci args->map_entries_st[ctx->pst_sp] = map->child_map_size; 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci return 0; 139d4afb5ceSopenharmony_ci} 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_cisigned char 142d4afb5ceSopenharmony_cilws_struct_default_lejp_cb(struct lejp_ctx *ctx, char reason) 143d4afb5ceSopenharmony_ci{ 144d4afb5ceSopenharmony_ci lws_struct_args_t *args = (lws_struct_args_t *)ctx->user; 145d4afb5ceSopenharmony_ci const lws_struct_map_t *map, *pmap = NULL; 146d4afb5ceSopenharmony_ci uint8_t *ch; 147d4afb5ceSopenharmony_ci size_t n; 148d4afb5ceSopenharmony_ci char *u; 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci if (reason == LEJPCB_ARRAY_END) { 151d4afb5ceSopenharmony_ci lejp_parser_pop(ctx); 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci return 0; 154d4afb5ceSopenharmony_ci } 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci if (reason == LEJPCB_ARRAY_START) { 157d4afb5ceSopenharmony_ci if (!ctx->path_match) 158d4afb5ceSopenharmony_ci lwsl_err("%s: ARRAY_START with ctx->path_match 0\n", __func__); 159d4afb5ceSopenharmony_ci map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci if (map->type == LSMT_LIST) 162d4afb5ceSopenharmony_ci lws_struct_lejp_push(ctx, args, map, NULL); 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci return 0; 165d4afb5ceSopenharmony_ci } 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci if (ctx->pst_sp) 168d4afb5ceSopenharmony_ci pmap = &args->map_st[ctx->pst_sp - 1] 169d4afb5ceSopenharmony_ci [ctx->pst[ctx->pst_sp - 1].path_match - 1]; 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci if (reason == LEJPCB_OBJECT_START) { 172d4afb5ceSopenharmony_ci 173d4afb5ceSopenharmony_ci if (!ctx->path_match) { 174d4afb5ceSopenharmony_ci ctx->pst[ctx->pst_sp].user = NULL; 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci return 0; 177d4afb5ceSopenharmony_ci } 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; 180d4afb5ceSopenharmony_ci n = args->map_entries_st[ctx->pst_sp]; 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci if (map->type != LSMT_CHILD_PTR && map->type != LSMT_LIST) { 183d4afb5ceSopenharmony_ci ctx->pst[ctx->pst_sp].user = NULL; 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci return 0; 186d4afb5ceSopenharmony_ci } 187d4afb5ceSopenharmony_ci pmap = map; 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci lws_struct_lejp_push(ctx, args, map, NULL); 190d4afb5ceSopenharmony_ci } 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci if (reason == LEJPCB_OBJECT_END && pmap) { 193d4afb5ceSopenharmony_ci if (pmap->type == LSMT_CHILD_PTR) 194d4afb5ceSopenharmony_ci lejp_parser_pop(ctx); 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci if (ctx->pst_sp) 197d4afb5ceSopenharmony_ci pmap = &args->map_st[ctx->pst_sp - 1] 198d4afb5ceSopenharmony_ci [ctx->pst[ctx->pst_sp - 1].path_match - 1]; 199d4afb5ceSopenharmony_ci } 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci if (!ctx->path_match) 202d4afb5ceSopenharmony_ci return 0; 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_ci map = &args->map_st[ctx->pst_sp][ctx->path_match - 1]; 205d4afb5ceSopenharmony_ci n = args->map_entries_st[ctx->pst_sp]; 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci if (map->type == LSMT_SCHEMA) { 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci while (n--) { 210d4afb5ceSopenharmony_ci if (strncmp(map->colname, ctx->buf, ctx->npos)) { 211d4afb5ceSopenharmony_ci map++; 212d4afb5ceSopenharmony_ci continue; 213d4afb5ceSopenharmony_ci } 214d4afb5ceSopenharmony_ci 215d4afb5ceSopenharmony_ci /* instantiate the correct toplevel object */ 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci ch = lwsac_use_zero(&args->ac, map->aux, 218d4afb5ceSopenharmony_ci args->ac_block_size); 219d4afb5ceSopenharmony_ci if (!ch) { 220d4afb5ceSopenharmony_ci lwsl_err("OOM\n"); 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci return 1; 223d4afb5ceSopenharmony_ci } 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci lws_struct_lejp_push(ctx, args, map, ch); 226d4afb5ceSopenharmony_ci 227d4afb5ceSopenharmony_ci return 0; 228d4afb5ceSopenharmony_ci } 229d4afb5ceSopenharmony_ci lwsl_notice("%s: unknown schema %.*s, tried %d\n", __func__, 230d4afb5ceSopenharmony_ci ctx->npos, ctx->buf, 231d4afb5ceSopenharmony_ci (int)args->map_entries_st[ctx->pst_sp]); 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci goto cleanup; 234d4afb5ceSopenharmony_ci } 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci if (!ctx->pst[ctx->pst_sp].user) { 237d4afb5ceSopenharmony_ci struct lws_dll2_owner *owner; 238d4afb5ceSopenharmony_ci struct lws_dll2 *list; 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_ci /* create list item object if none already */ 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci if (!ctx->path_match || !pmap) 243d4afb5ceSopenharmony_ci return 0; 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci map = &args->map_st[ctx->pst_sp - 1][ctx->path_match - 1]; 246d4afb5ceSopenharmony_ci n = args->map_entries_st[ctx->pst_sp - 1]; 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci if (!ctx->pst_sp) 249d4afb5ceSopenharmony_ci return 0; 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci if (pmap->type != LSMT_LIST && pmap->type != LSMT_CHILD_PTR) 252d4afb5ceSopenharmony_ci return 1; 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci /* we need to create a child or array item object */ 255d4afb5ceSopenharmony_ci 256d4afb5ceSopenharmony_ci owner = (struct lws_dll2_owner *) 257d4afb5ceSopenharmony_ci (((char *)ctx->pst[ctx->pst_sp - 1].user) + pmap->ofs); 258d4afb5ceSopenharmony_ci 259d4afb5ceSopenharmony_ci assert(pmap->aux); 260d4afb5ceSopenharmony_ci 261d4afb5ceSopenharmony_ci /* instantiate one of the child objects */ 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_ci ctx->pst[ctx->pst_sp].user = lwsac_use_zero(&args->ac, 264d4afb5ceSopenharmony_ci pmap->aux, args->ac_block_size); 265d4afb5ceSopenharmony_ci if (!ctx->pst[ctx->pst_sp].user) { 266d4afb5ceSopenharmony_ci lwsl_err("OOM\n"); 267d4afb5ceSopenharmony_ci 268d4afb5ceSopenharmony_ci return 1; 269d4afb5ceSopenharmony_ci } 270d4afb5ceSopenharmony_ci lwsl_info("%s: created '%s' object size %d\n", __func__, 271d4afb5ceSopenharmony_ci pmap->colname, (int)pmap->aux); 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci switch (pmap->type) { 274d4afb5ceSopenharmony_ci case LSMT_LIST: 275d4afb5ceSopenharmony_ci list = (struct lws_dll2 *) 276d4afb5ceSopenharmony_ci ((char *)ctx->pst[ctx->pst_sp].user + 277d4afb5ceSopenharmony_ci pmap->ofs_clist); 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci lws_dll2_add_tail(list, owner); 280d4afb5ceSopenharmony_ci break; 281d4afb5ceSopenharmony_ci case LSMT_CHILD_PTR: 282d4afb5ceSopenharmony_ci *((void **)owner) = ctx->pst[ctx->pst_sp].user; 283d4afb5ceSopenharmony_ci break; 284d4afb5ceSopenharmony_ci default: 285d4afb5ceSopenharmony_ci assert(0); 286d4afb5ceSopenharmony_ci break; 287d4afb5ceSopenharmony_ci } 288d4afb5ceSopenharmony_ci } 289d4afb5ceSopenharmony_ci 290d4afb5ceSopenharmony_ci if (!ctx->path_match) 291d4afb5ceSopenharmony_ci return 0; 292d4afb5ceSopenharmony_ci 293d4afb5ceSopenharmony_ci if (reason == LEJPCB_VAL_STR_CHUNK) { 294d4afb5ceSopenharmony_ci lejp_collation_t *coll; 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci /* don't cache stuff we are going to ignore */ 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci if (map->type == LSMT_STRING_CHAR_ARRAY && 299d4afb5ceSopenharmony_ci args->chunks_length >= map->aux) 300d4afb5ceSopenharmony_ci return 0; 301d4afb5ceSopenharmony_ci 302d4afb5ceSopenharmony_ci coll = lwsac_use_zero(&args->ac_chunks, sizeof(*coll), 303d4afb5ceSopenharmony_ci sizeof(*coll)); 304d4afb5ceSopenharmony_ci if (!coll) { 305d4afb5ceSopenharmony_ci lwsl_err("%s: OOT\n", __func__); 306d4afb5ceSopenharmony_ci 307d4afb5ceSopenharmony_ci return 1; 308d4afb5ceSopenharmony_ci } 309d4afb5ceSopenharmony_ci coll->chunks.prev = NULL; 310d4afb5ceSopenharmony_ci coll->chunks.next = NULL; 311d4afb5ceSopenharmony_ci coll->chunks.owner = NULL; 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ci coll->len = ctx->npos; 314d4afb5ceSopenharmony_ci lws_dll2_add_tail(&coll->chunks, &args->chunks_owner); 315d4afb5ceSopenharmony_ci 316d4afb5ceSopenharmony_ci memcpy(coll->buf, ctx->buf, ctx->npos); 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci args->chunks_length += ctx->npos; 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci return 0; 321d4afb5ceSopenharmony_ci } 322d4afb5ceSopenharmony_ci 323d4afb5ceSopenharmony_ci if (reason != LEJPCB_VAL_STR_END && reason != LEJPCB_VAL_NUM_INT && 324d4afb5ceSopenharmony_ci reason != LEJPCB_VAL_TRUE && reason != LEJPCB_VAL_FALSE) 325d4afb5ceSopenharmony_ci return 0; 326d4afb5ceSopenharmony_ci 327d4afb5ceSopenharmony_ci /* this is the end of the string */ 328d4afb5ceSopenharmony_ci 329d4afb5ceSopenharmony_ci if (ctx->pst[ctx->pst_sp].user && pmap && pmap->type == LSMT_CHILD_PTR) { 330d4afb5ceSopenharmony_ci void **pp = (void **) 331d4afb5ceSopenharmony_ci (((char *)ctx->pst[ctx->pst_sp - 1].user) + pmap->ofs); 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci *pp = ctx->pst[ctx->pst_sp].user; 334d4afb5ceSopenharmony_ci } 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_ci u = (char *)ctx->pst[ctx->pst_sp].user; 337d4afb5ceSopenharmony_ci if (!u) 338d4afb5ceSopenharmony_ci u = (char *)ctx->pst[ctx->pst_sp - 1].user; 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci { 341d4afb5ceSopenharmony_ci char **pp, *s; 342d4afb5ceSopenharmony_ci size_t lim, b; 343d4afb5ceSopenharmony_ci long long li; 344d4afb5ceSopenharmony_ci 345d4afb5ceSopenharmony_ci switch (map->type) { 346d4afb5ceSopenharmony_ci case LSMT_SIGNED: 347d4afb5ceSopenharmony_ci if (map->aux == sizeof(signed char)) { 348d4afb5ceSopenharmony_ci signed char *pc; 349d4afb5ceSopenharmony_ci pc = (signed char *)(u + map->ofs); 350d4afb5ceSopenharmony_ci *pc = (signed char)atoi(ctx->buf); 351d4afb5ceSopenharmony_ci break; 352d4afb5ceSopenharmony_ci } 353d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 354d4afb5ceSopenharmony_ci int *pi; 355d4afb5ceSopenharmony_ci pi = (int *)(u + map->ofs); 356d4afb5ceSopenharmony_ci *pi = atoi(ctx->buf); 357d4afb5ceSopenharmony_ci break; 358d4afb5ceSopenharmony_ci } 359d4afb5ceSopenharmony_ci if (map->aux == sizeof(long)) { 360d4afb5ceSopenharmony_ci long *pl; 361d4afb5ceSopenharmony_ci pl = (long *)(u + map->ofs); 362d4afb5ceSopenharmony_ci *pl = atol(ctx->buf); 363d4afb5ceSopenharmony_ci } else { 364d4afb5ceSopenharmony_ci long long *pll; 365d4afb5ceSopenharmony_ci pll = (long long *)(u + map->ofs); 366d4afb5ceSopenharmony_ci *pll = atoll(ctx->buf); 367d4afb5ceSopenharmony_ci } 368d4afb5ceSopenharmony_ci break; 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci case LSMT_UNSIGNED: 371d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned char)) { 372d4afb5ceSopenharmony_ci unsigned char *pc; 373d4afb5ceSopenharmony_ci pc = (unsigned char *)(u + map->ofs); 374d4afb5ceSopenharmony_ci *pc = (unsigned char)(unsigned int)atoi(ctx->buf); 375d4afb5ceSopenharmony_ci break; 376d4afb5ceSopenharmony_ci } 377d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned int)) { 378d4afb5ceSopenharmony_ci unsigned int *pi; 379d4afb5ceSopenharmony_ci pi = (unsigned int *)(u + map->ofs); 380d4afb5ceSopenharmony_ci *pi = (unsigned int)atoi(ctx->buf); 381d4afb5ceSopenharmony_ci break; 382d4afb5ceSopenharmony_ci } 383d4afb5ceSopenharmony_ci if (map->aux == sizeof(unsigned long)) { 384d4afb5ceSopenharmony_ci unsigned long *pl; 385d4afb5ceSopenharmony_ci pl = (unsigned long *)(u + map->ofs); 386d4afb5ceSopenharmony_ci *pl = (unsigned long)atol(ctx->buf); 387d4afb5ceSopenharmony_ci } else { 388d4afb5ceSopenharmony_ci unsigned long long *pll; 389d4afb5ceSopenharmony_ci pll = (unsigned long long *)(u + map->ofs); 390d4afb5ceSopenharmony_ci *pll = (unsigned long long)atoll(ctx->buf); 391d4afb5ceSopenharmony_ci } 392d4afb5ceSopenharmony_ci break; 393d4afb5ceSopenharmony_ci 394d4afb5ceSopenharmony_ci case LSMT_BOOLEAN: 395d4afb5ceSopenharmony_ci li = reason == LEJPCB_VAL_TRUE; 396d4afb5ceSopenharmony_ci if (map->aux == sizeof(char)) { 397d4afb5ceSopenharmony_ci char *pc; 398d4afb5ceSopenharmony_ci pc = (char *)(u + map->ofs); 399d4afb5ceSopenharmony_ci *pc = (char)li; 400d4afb5ceSopenharmony_ci break; 401d4afb5ceSopenharmony_ci } 402d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 403d4afb5ceSopenharmony_ci int *pi; 404d4afb5ceSopenharmony_ci pi = (int *)(u + map->ofs); 405d4afb5ceSopenharmony_ci *pi = (int)li; 406d4afb5ceSopenharmony_ci } else { 407d4afb5ceSopenharmony_ci uint64_t *p64; 408d4afb5ceSopenharmony_ci p64 = (uint64_t *)(u + map->ofs); 409d4afb5ceSopenharmony_ci *p64 = (uint64_t)li; 410d4afb5ceSopenharmony_ci } 411d4afb5ceSopenharmony_ci break; 412d4afb5ceSopenharmony_ci 413d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 414d4afb5ceSopenharmony_ci s = (char *)(u + map->ofs); 415d4afb5ceSopenharmony_ci lim = map->aux - 1; 416d4afb5ceSopenharmony_ci goto chunk_copy; 417d4afb5ceSopenharmony_ci 418d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 419d4afb5ceSopenharmony_ci pp = (char **)(u + map->ofs); 420d4afb5ceSopenharmony_ci lim = args->chunks_length + ctx->npos; 421d4afb5ceSopenharmony_ci s = lwsac_use(&args->ac, lim + 1, args->ac_block_size); 422d4afb5ceSopenharmony_ci if (!s) 423d4afb5ceSopenharmony_ci goto cleanup; 424d4afb5ceSopenharmony_ci *pp = s; 425d4afb5ceSopenharmony_ci 426d4afb5ceSopenharmony_cichunk_copy: 427d4afb5ceSopenharmony_ci s[lim] = '\0'; 428d4afb5ceSopenharmony_ci /* copy up to lim from the string chunk ac first */ 429d4afb5ceSopenharmony_ci lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1, 430d4afb5ceSopenharmony_ci args->chunks_owner.head) { 431d4afb5ceSopenharmony_ci lejp_collation_t *coll = (lejp_collation_t *)p; 432d4afb5ceSopenharmony_ci 433d4afb5ceSopenharmony_ci if (lim) { 434d4afb5ceSopenharmony_ci b = (unsigned int)coll->len; 435d4afb5ceSopenharmony_ci if (b > lim) 436d4afb5ceSopenharmony_ci b = lim; 437d4afb5ceSopenharmony_ci memcpy(s, coll->buf, b); 438d4afb5ceSopenharmony_ci s += b; 439d4afb5ceSopenharmony_ci lim -= b; 440d4afb5ceSopenharmony_ci } 441d4afb5ceSopenharmony_ci } lws_end_foreach_dll_safe(p, p1); 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci lwsac_free(&args->ac_chunks); 444d4afb5ceSopenharmony_ci args->chunks_owner.count = 0; 445d4afb5ceSopenharmony_ci args->chunks_owner.head = NULL; 446d4afb5ceSopenharmony_ci args->chunks_owner.tail = NULL; 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_ci if (lim) { 449d4afb5ceSopenharmony_ci b = ctx->npos; 450d4afb5ceSopenharmony_ci if (b > lim) 451d4afb5ceSopenharmony_ci b = lim; 452d4afb5ceSopenharmony_ci memcpy(s, ctx->buf, b); 453d4afb5ceSopenharmony_ci s[b] = '\0'; 454d4afb5ceSopenharmony_ci } 455d4afb5ceSopenharmony_ci break; 456d4afb5ceSopenharmony_ci default: 457d4afb5ceSopenharmony_ci break; 458d4afb5ceSopenharmony_ci } 459d4afb5ceSopenharmony_ci } 460d4afb5ceSopenharmony_ci 461d4afb5ceSopenharmony_ci if (args->cb) 462d4afb5ceSopenharmony_ci args->cb(args->dest, args->cb_arg); 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ci return 0; 465d4afb5ceSopenharmony_ci 466d4afb5ceSopenharmony_cicleanup: 467d4afb5ceSopenharmony_ci lwsl_notice("%s: cleanup\n", __func__); 468d4afb5ceSopenharmony_ci lwsac_free(&args->ac_chunks); 469d4afb5ceSopenharmony_ci args->chunks_owner.count = 0; 470d4afb5ceSopenharmony_ci args->chunks_owner.head = NULL; 471d4afb5ceSopenharmony_ci args->chunks_owner.tail = NULL; 472d4afb5ceSopenharmony_ci 473d4afb5ceSopenharmony_ci return 1; 474d4afb5ceSopenharmony_ci} 475d4afb5ceSopenharmony_ci 476d4afb5ceSopenharmony_cistatic const char * schema[] = { "schema" }; 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_ciint 479d4afb5ceSopenharmony_cilws_struct_json_init_parse(struct lejp_ctx *ctx, lejp_callback cb, void *user) 480d4afb5ceSopenharmony_ci{ 481d4afb5ceSopenharmony_ci /* 482d4afb5ceSopenharmony_ci * By default we are looking to match on a toplevel member called 483d4afb5ceSopenharmony_ci * "schema", against an LSM_SCHEMA 484d4afb5ceSopenharmony_ci */ 485d4afb5ceSopenharmony_ci if (!cb) 486d4afb5ceSopenharmony_ci cb = lws_struct_schema_only_lejp_cb; 487d4afb5ceSopenharmony_ci lejp_construct(ctx, cb, user, schema, 1); 488d4afb5ceSopenharmony_ci 489d4afb5ceSopenharmony_ci ctx->path_stride = sizeof(lws_struct_map_t); 490d4afb5ceSopenharmony_ci 491d4afb5ceSopenharmony_ci return 0; 492d4afb5ceSopenharmony_ci} 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_cilws_struct_serialize_t * 495d4afb5ceSopenharmony_cilws_struct_json_serialize_create(const lws_struct_map_t *map, 496d4afb5ceSopenharmony_ci size_t map_entries, int flags, 497d4afb5ceSopenharmony_ci const void *ptoplevel) 498d4afb5ceSopenharmony_ci{ 499d4afb5ceSopenharmony_ci lws_struct_serialize_t *js = lws_zalloc(sizeof(*js), __func__); 500d4afb5ceSopenharmony_ci lws_struct_serialize_st_t *j; 501d4afb5ceSopenharmony_ci 502d4afb5ceSopenharmony_ci if (!js) 503d4afb5ceSopenharmony_ci return NULL; 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci js->flags = flags; 506d4afb5ceSopenharmony_ci 507d4afb5ceSopenharmony_ci j = &js->st[0]; 508d4afb5ceSopenharmony_ci j->map = map; 509d4afb5ceSopenharmony_ci j->map_entries = map_entries; 510d4afb5ceSopenharmony_ci j->obj = ptoplevel; 511d4afb5ceSopenharmony_ci j->idt = 0; 512d4afb5ceSopenharmony_ci 513d4afb5ceSopenharmony_ci return js; 514d4afb5ceSopenharmony_ci} 515d4afb5ceSopenharmony_ci 516d4afb5ceSopenharmony_civoid 517d4afb5ceSopenharmony_cilws_struct_json_serialize_destroy(lws_struct_serialize_t **pjs) 518d4afb5ceSopenharmony_ci{ 519d4afb5ceSopenharmony_ci if (!*pjs) 520d4afb5ceSopenharmony_ci return; 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci lws_free(*pjs); 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci *pjs = NULL; 525d4afb5ceSopenharmony_ci} 526d4afb5ceSopenharmony_ci 527d4afb5ceSopenharmony_cistatic void 528d4afb5ceSopenharmony_cilws_struct_pretty(lws_struct_serialize_t *js, uint8_t **pbuf, size_t *plen) 529d4afb5ceSopenharmony_ci{ 530d4afb5ceSopenharmony_ci if (js->flags & LSSERJ_FLAG_PRETTY) { 531d4afb5ceSopenharmony_ci int n; 532d4afb5ceSopenharmony_ci 533d4afb5ceSopenharmony_ci *(*pbuf)++ = '\n'; 534d4afb5ceSopenharmony_ci (*plen)--; 535d4afb5ceSopenharmony_ci for (n = 0; n < js->st[js->sp].idt; n++) { 536d4afb5ceSopenharmony_ci *(*pbuf)++ = ' '; 537d4afb5ceSopenharmony_ci (*plen)--; 538d4afb5ceSopenharmony_ci } 539d4afb5ceSopenharmony_ci } 540d4afb5ceSopenharmony_ci} 541d4afb5ceSopenharmony_ci 542d4afb5ceSopenharmony_cilws_struct_json_serialize_result_t 543d4afb5ceSopenharmony_cilws_struct_json_serialize(lws_struct_serialize_t *js, uint8_t *buf, 544d4afb5ceSopenharmony_ci size_t len, size_t *written) 545d4afb5ceSopenharmony_ci{ 546d4afb5ceSopenharmony_ci lws_struct_serialize_st_t *j; 547d4afb5ceSopenharmony_ci const lws_struct_map_t *map; 548d4afb5ceSopenharmony_ci size_t budget = 0, olen = len, m; 549d4afb5ceSopenharmony_ci struct lws_dll2_owner *o; 550d4afb5ceSopenharmony_ci unsigned long long uli; 551d4afb5ceSopenharmony_ci const char *q; 552d4afb5ceSopenharmony_ci const void *p; 553d4afb5ceSopenharmony_ci char dbuf[72]; 554d4afb5ceSopenharmony_ci long long li; 555d4afb5ceSopenharmony_ci int n, used; 556d4afb5ceSopenharmony_ci 557d4afb5ceSopenharmony_ci *written = 0; 558d4afb5ceSopenharmony_ci *buf = '\0'; 559d4afb5ceSopenharmony_ci 560d4afb5ceSopenharmony_ci while (len > sizeof(dbuf) + 20) { 561d4afb5ceSopenharmony_ci j = &js->st[js->sp]; 562d4afb5ceSopenharmony_ci map = &j->map[j->map_entry]; 563d4afb5ceSopenharmony_ci q = j->obj + map->ofs; 564d4afb5ceSopenharmony_ci 565d4afb5ceSopenharmony_ci /* early check if the entry should be elided */ 566d4afb5ceSopenharmony_ci 567d4afb5ceSopenharmony_ci switch (map->type) { 568d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 569d4afb5ceSopenharmony_ci if (!q) 570d4afb5ceSopenharmony_ci goto up; 571d4afb5ceSopenharmony_ci break; 572d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 573d4afb5ceSopenharmony_ci case LSMT_CHILD_PTR: 574d4afb5ceSopenharmony_ci q = (char *)*(char **)q; 575d4afb5ceSopenharmony_ci if (!q) 576d4afb5ceSopenharmony_ci goto up; 577d4afb5ceSopenharmony_ci break; 578d4afb5ceSopenharmony_ci 579d4afb5ceSopenharmony_ci case LSMT_LIST: 580d4afb5ceSopenharmony_ci o = (struct lws_dll2_owner *)q; 581d4afb5ceSopenharmony_ci p = j->dllpos = lws_dll2_get_head(o); 582d4afb5ceSopenharmony_ci if (!p) 583d4afb5ceSopenharmony_ci goto up; 584d4afb5ceSopenharmony_ci break; 585d4afb5ceSopenharmony_ci 586d4afb5ceSopenharmony_ci case LSMT_BLOB_PTR: 587d4afb5ceSopenharmony_ci goto up; 588d4afb5ceSopenharmony_ci 589d4afb5ceSopenharmony_ci default: 590d4afb5ceSopenharmony_ci break; 591d4afb5ceSopenharmony_ci } 592d4afb5ceSopenharmony_ci 593d4afb5ceSopenharmony_ci if (j->subsequent) { 594d4afb5ceSopenharmony_ci *buf++ = ','; 595d4afb5ceSopenharmony_ci len--; 596d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 597d4afb5ceSopenharmony_ci } 598d4afb5ceSopenharmony_ci j->subsequent = 1; 599d4afb5ceSopenharmony_ci 600d4afb5ceSopenharmony_ci if (map->type != LSMT_SCHEMA && !js->offset) { 601d4afb5ceSopenharmony_ci n = lws_snprintf((char *)buf, len, "\"%s\":", 602d4afb5ceSopenharmony_ci map->colname); 603d4afb5ceSopenharmony_ci buf += n; 604d4afb5ceSopenharmony_ci len = len - (unsigned int)n; 605d4afb5ceSopenharmony_ci if (js->flags & LSSERJ_FLAG_PRETTY) { 606d4afb5ceSopenharmony_ci *buf++ = ' '; 607d4afb5ceSopenharmony_ci len--; 608d4afb5ceSopenharmony_ci } 609d4afb5ceSopenharmony_ci } 610d4afb5ceSopenharmony_ci 611d4afb5ceSopenharmony_ci switch (map->type) { 612d4afb5ceSopenharmony_ci case LSMT_BOOLEAN: 613d4afb5ceSopenharmony_ci case LSMT_UNSIGNED: 614d4afb5ceSopenharmony_ci if (map->aux == sizeof(char)) { 615d4afb5ceSopenharmony_ci uli = *(unsigned char *)q; 616d4afb5ceSopenharmony_ci } else { 617d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 618d4afb5ceSopenharmony_ci uli = *(unsigned int *)q; 619d4afb5ceSopenharmony_ci } else { 620d4afb5ceSopenharmony_ci if (map->aux == sizeof(long)) 621d4afb5ceSopenharmony_ci uli = *(unsigned long *)q; 622d4afb5ceSopenharmony_ci else 623d4afb5ceSopenharmony_ci uli = *(unsigned long long *)q; 624d4afb5ceSopenharmony_ci } 625d4afb5ceSopenharmony_ci } 626d4afb5ceSopenharmony_ci q = dbuf; 627d4afb5ceSopenharmony_ci 628d4afb5ceSopenharmony_ci if (map->type == LSMT_BOOLEAN) { 629d4afb5ceSopenharmony_ci budget = (unsigned int)lws_snprintf(dbuf, sizeof(dbuf), 630d4afb5ceSopenharmony_ci "%s", uli ? "true" : "false"); 631d4afb5ceSopenharmony_ci } else 632d4afb5ceSopenharmony_ci budget = (unsigned int)lws_snprintf(dbuf, sizeof(dbuf), 633d4afb5ceSopenharmony_ci "%llu", uli); 634d4afb5ceSopenharmony_ci break; 635d4afb5ceSopenharmony_ci 636d4afb5ceSopenharmony_ci case LSMT_SIGNED: 637d4afb5ceSopenharmony_ci if (map->aux == sizeof(signed char)) { 638d4afb5ceSopenharmony_ci li = (long long)*(signed char *)q; 639d4afb5ceSopenharmony_ci } else { 640d4afb5ceSopenharmony_ci if (map->aux == sizeof(int)) { 641d4afb5ceSopenharmony_ci li = (long long)*(int *)q; 642d4afb5ceSopenharmony_ci } else { 643d4afb5ceSopenharmony_ci if (map->aux == sizeof(long)) 644d4afb5ceSopenharmony_ci li = (long long)*(long *)q; 645d4afb5ceSopenharmony_ci else 646d4afb5ceSopenharmony_ci li = *(long long *)q; 647d4afb5ceSopenharmony_ci } 648d4afb5ceSopenharmony_ci } 649d4afb5ceSopenharmony_ci q = dbuf; 650d4afb5ceSopenharmony_ci budget = (unsigned int)lws_snprintf(dbuf, sizeof(dbuf), "%lld", li); 651d4afb5ceSopenharmony_ci break; 652d4afb5ceSopenharmony_ci 653d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 654d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 655d4afb5ceSopenharmony_ci if (!js->offset) { 656d4afb5ceSopenharmony_ci *buf++ = '\"'; 657d4afb5ceSopenharmony_ci len--; 658d4afb5ceSopenharmony_ci } 659d4afb5ceSopenharmony_ci break; 660d4afb5ceSopenharmony_ci 661d4afb5ceSopenharmony_ci case LSMT_LIST: 662d4afb5ceSopenharmony_ci *buf++ = '['; 663d4afb5ceSopenharmony_ci len--; 664d4afb5ceSopenharmony_ci if (js->sp + 1 == LEJP_MAX_PARSING_STACK_DEPTH) 665d4afb5ceSopenharmony_ci return LSJS_RESULT_ERROR; 666d4afb5ceSopenharmony_ci 667d4afb5ceSopenharmony_ci /* add a stack level to handle parsing array members */ 668d4afb5ceSopenharmony_ci 669d4afb5ceSopenharmony_ci o = (struct lws_dll2_owner *)q; 670d4afb5ceSopenharmony_ci p = j->dllpos = lws_dll2_get_head(o); 671d4afb5ceSopenharmony_ci 672d4afb5ceSopenharmony_ci if (!j->dllpos) { 673d4afb5ceSopenharmony_ci *buf++ = ']'; 674d4afb5ceSopenharmony_ci len--; 675d4afb5ceSopenharmony_ci goto up; 676d4afb5ceSopenharmony_ci } 677d4afb5ceSopenharmony_ci 678d4afb5ceSopenharmony_ci n = j->idt; 679d4afb5ceSopenharmony_ci j = &js->st[++js->sp]; 680d4afb5ceSopenharmony_ci j->idt = (char)(n + 2); 681d4afb5ceSopenharmony_ci j->map = map->child_map; 682d4afb5ceSopenharmony_ci j->map_entries = map->child_map_size; 683d4afb5ceSopenharmony_ci j->size = map->aux; 684d4afb5ceSopenharmony_ci j->subsequent = 0; 685d4afb5ceSopenharmony_ci j->map_entry = 0; 686d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 687d4afb5ceSopenharmony_ci *buf++ = '{'; 688d4afb5ceSopenharmony_ci len--; 689d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 690d4afb5ceSopenharmony_ci if (p) 691d4afb5ceSopenharmony_ci j->obj = ((char *)p) - j->map->ofs_clist; 692d4afb5ceSopenharmony_ci else 693d4afb5ceSopenharmony_ci j->obj = NULL; 694d4afb5ceSopenharmony_ci continue; 695d4afb5ceSopenharmony_ci 696d4afb5ceSopenharmony_ci case LSMT_CHILD_PTR: 697d4afb5ceSopenharmony_ci 698d4afb5ceSopenharmony_ci if (js->sp + 1 == LEJP_MAX_PARSING_STACK_DEPTH) 699d4afb5ceSopenharmony_ci return LSJS_RESULT_ERROR; 700d4afb5ceSopenharmony_ci 701d4afb5ceSopenharmony_ci /* add a stack level to handle parsing child members */ 702d4afb5ceSopenharmony_ci 703d4afb5ceSopenharmony_ci n = j->idt; 704d4afb5ceSopenharmony_ci j = &js->st[++js->sp]; 705d4afb5ceSopenharmony_ci j->idt = (char)(n + 2); 706d4afb5ceSopenharmony_ci j->map = map->child_map; 707d4afb5ceSopenharmony_ci j->map_entries = map->child_map_size; 708d4afb5ceSopenharmony_ci j->size = map->aux; 709d4afb5ceSopenharmony_ci j->subsequent = 0; 710d4afb5ceSopenharmony_ci j->map_entry = 0; 711d4afb5ceSopenharmony_ci *buf++ = '{'; 712d4afb5ceSopenharmony_ci len--; 713d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 714d4afb5ceSopenharmony_ci j->obj = q; 715d4afb5ceSopenharmony_ci 716d4afb5ceSopenharmony_ci continue; 717d4afb5ceSopenharmony_ci 718d4afb5ceSopenharmony_ci case LSMT_SCHEMA: 719d4afb5ceSopenharmony_ci q = dbuf; 720d4afb5ceSopenharmony_ci *buf++ = '{'; 721d4afb5ceSopenharmony_ci len--; 722d4afb5ceSopenharmony_ci j = &js->st[++js->sp]; 723d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 724d4afb5ceSopenharmony_ci if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) { 725d4afb5ceSopenharmony_ci budget = (unsigned int)lws_snprintf(dbuf, 15, "\"schema\":"); 726d4afb5ceSopenharmony_ci if (js->flags & LSSERJ_FLAG_PRETTY) 727d4afb5ceSopenharmony_ci dbuf[budget++] = ' '; 728d4afb5ceSopenharmony_ci 729d4afb5ceSopenharmony_ci budget += (unsigned int)lws_snprintf(dbuf + budget, 730d4afb5ceSopenharmony_ci sizeof(dbuf) - budget, 731d4afb5ceSopenharmony_ci "\"%s\"", map->colname); 732d4afb5ceSopenharmony_ci } 733d4afb5ceSopenharmony_ci 734d4afb5ceSopenharmony_ci 735d4afb5ceSopenharmony_ci if (js->sp != 1) 736d4afb5ceSopenharmony_ci return LSJS_RESULT_ERROR; 737d4afb5ceSopenharmony_ci j->map = map->child_map; 738d4afb5ceSopenharmony_ci j->map_entries = map->child_map_size; 739d4afb5ceSopenharmony_ci j->size = map->aux; 740d4afb5ceSopenharmony_ci j->subsequent = 0; 741d4afb5ceSopenharmony_ci j->map_entry = 0; 742d4afb5ceSopenharmony_ci j->obj = js->st[js->sp - 1].obj; 743d4afb5ceSopenharmony_ci j->dllpos = NULL; 744d4afb5ceSopenharmony_ci if (!(js->flags & LSSERJ_FLAG_OMIT_SCHEMA)) 745d4afb5ceSopenharmony_ci /* we're actually at the same level */ 746d4afb5ceSopenharmony_ci j->subsequent = 1; 747d4afb5ceSopenharmony_ci j->idt = 1; 748d4afb5ceSopenharmony_ci break; 749d4afb5ceSopenharmony_ci default: 750d4afb5ceSopenharmony_ci break; 751d4afb5ceSopenharmony_ci } 752d4afb5ceSopenharmony_ci 753d4afb5ceSopenharmony_ci switch (map->type) { 754d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 755d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 756d4afb5ceSopenharmony_ci /* 757d4afb5ceSopenharmony_ci * This is a bit tricky... we have to escape the string 758d4afb5ceSopenharmony_ci * which may 6x its length depending on what the 759d4afb5ceSopenharmony_ci * contents are. 760d4afb5ceSopenharmony_ci * 761d4afb5ceSopenharmony_ci * We offset the unescaped string starting point first 762d4afb5ceSopenharmony_ci */ 763d4afb5ceSopenharmony_ci 764d4afb5ceSopenharmony_ci q += js->offset; 765d4afb5ceSopenharmony_ci budget = strlen(q); /* how much unescaped is left */ 766d4afb5ceSopenharmony_ci 767d4afb5ceSopenharmony_ci /* 768d4afb5ceSopenharmony_ci * This is going to escape as much as it can fit, and 769d4afb5ceSopenharmony_ci * let us know the amount of input that was consumed 770d4afb5ceSopenharmony_ci * in "used". 771d4afb5ceSopenharmony_ci */ 772d4afb5ceSopenharmony_ci 773d4afb5ceSopenharmony_ci lws_json_purify((char *)buf, q, (int)len, &used); 774d4afb5ceSopenharmony_ci m = strlen((const char *)buf); 775d4afb5ceSopenharmony_ci buf += m; 776d4afb5ceSopenharmony_ci len -= m; 777d4afb5ceSopenharmony_ci js->remaining = budget - (unsigned int)used; 778d4afb5ceSopenharmony_ci js->offset = (unsigned int)used; 779d4afb5ceSopenharmony_ci if (!js->remaining) 780d4afb5ceSopenharmony_ci js->offset = 0; 781d4afb5ceSopenharmony_ci 782d4afb5ceSopenharmony_ci break; 783d4afb5ceSopenharmony_ci default: 784d4afb5ceSopenharmony_ci q += js->offset; 785d4afb5ceSopenharmony_ci budget -= js->remaining; 786d4afb5ceSopenharmony_ci 787d4afb5ceSopenharmony_ci if (budget > len) { 788d4afb5ceSopenharmony_ci js->remaining = budget - len; 789d4afb5ceSopenharmony_ci js->offset = len; 790d4afb5ceSopenharmony_ci budget = len; 791d4afb5ceSopenharmony_ci } else { 792d4afb5ceSopenharmony_ci js->remaining = 0; 793d4afb5ceSopenharmony_ci js->offset = 0; 794d4afb5ceSopenharmony_ci } 795d4afb5ceSopenharmony_ci 796d4afb5ceSopenharmony_ci memcpy(buf, q, budget); 797d4afb5ceSopenharmony_ci buf += budget; 798d4afb5ceSopenharmony_ci *buf = '\0'; 799d4afb5ceSopenharmony_ci len -= budget; 800d4afb5ceSopenharmony_ci break; 801d4afb5ceSopenharmony_ci } 802d4afb5ceSopenharmony_ci 803d4afb5ceSopenharmony_ci 804d4afb5ceSopenharmony_ci 805d4afb5ceSopenharmony_ci switch (map->type) { 806d4afb5ceSopenharmony_ci case LSMT_STRING_CHAR_ARRAY: 807d4afb5ceSopenharmony_ci case LSMT_STRING_PTR: 808d4afb5ceSopenharmony_ci *buf++ = '\"'; 809d4afb5ceSopenharmony_ci len--; 810d4afb5ceSopenharmony_ci break; 811d4afb5ceSopenharmony_ci case LSMT_SCHEMA: 812d4afb5ceSopenharmony_ci continue; 813d4afb5ceSopenharmony_ci default: 814d4afb5ceSopenharmony_ci break; 815d4afb5ceSopenharmony_ci } 816d4afb5ceSopenharmony_ci 817d4afb5ceSopenharmony_ci if (js->remaining) 818d4afb5ceSopenharmony_ci continue; 819d4afb5ceSopenharmony_ciup: 820d4afb5ceSopenharmony_ci if (++j->map_entry < j->map_entries) 821d4afb5ceSopenharmony_ci continue; 822d4afb5ceSopenharmony_ci 823d4afb5ceSopenharmony_ci if (!js->sp) 824d4afb5ceSopenharmony_ci continue; 825d4afb5ceSopenharmony_ci js->sp--; 826d4afb5ceSopenharmony_ci if (!js->sp) { 827d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 828d4afb5ceSopenharmony_ci *buf++ = '}'; 829d4afb5ceSopenharmony_ci len--; 830d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 831d4afb5ceSopenharmony_ci break; 832d4afb5ceSopenharmony_ci } 833d4afb5ceSopenharmony_ci js->offset = 0; 834d4afb5ceSopenharmony_ci j = &js->st[js->sp]; 835d4afb5ceSopenharmony_ci map = &j->map[j->map_entry]; 836d4afb5ceSopenharmony_ci 837d4afb5ceSopenharmony_ci if (map->type == LSMT_CHILD_PTR) { 838d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 839d4afb5ceSopenharmony_ci *buf++ = '}'; 840d4afb5ceSopenharmony_ci len--; 841d4afb5ceSopenharmony_ci 842d4afb5ceSopenharmony_ci /* we have done the singular child pointer */ 843d4afb5ceSopenharmony_ci 844d4afb5ceSopenharmony_ci js->offset = 0; 845d4afb5ceSopenharmony_ci goto up; 846d4afb5ceSopenharmony_ci } 847d4afb5ceSopenharmony_ci 848d4afb5ceSopenharmony_ci if (map->type != LSMT_LIST) 849d4afb5ceSopenharmony_ci continue; 850d4afb5ceSopenharmony_ci /* 851d4afb5ceSopenharmony_ci * we are coming back up to an array map, it means we should 852d4afb5ceSopenharmony_ci * advance to the next array member if there is one 853d4afb5ceSopenharmony_ci */ 854d4afb5ceSopenharmony_ci 855d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 856d4afb5ceSopenharmony_ci *buf++ = '}'; 857d4afb5ceSopenharmony_ci len--; 858d4afb5ceSopenharmony_ci 859d4afb5ceSopenharmony_ci p = j->dllpos = j->dllpos->next; 860d4afb5ceSopenharmony_ci if (j->dllpos) { 861d4afb5ceSopenharmony_ci /* 862d4afb5ceSopenharmony_ci * there was another item in the array to do... let's 863d4afb5ceSopenharmony_ci * move on to that and do it 864d4afb5ceSopenharmony_ci */ 865d4afb5ceSopenharmony_ci *buf++ = ','; 866d4afb5ceSopenharmony_ci len--; 867d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 868d4afb5ceSopenharmony_ci js->offset = 0; 869d4afb5ceSopenharmony_ci j = &js->st[++js->sp]; 870d4afb5ceSopenharmony_ci j->map_entry = 0; 871d4afb5ceSopenharmony_ci map = &j->map[j->map_entry]; 872d4afb5ceSopenharmony_ci 873d4afb5ceSopenharmony_ci *buf++ = '{'; 874d4afb5ceSopenharmony_ci len--; 875d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 876d4afb5ceSopenharmony_ci 877d4afb5ceSopenharmony_ci j->subsequent = 0; 878d4afb5ceSopenharmony_ci j->obj = ((char *)p) - j->map->ofs_clist; 879d4afb5ceSopenharmony_ci continue; 880d4afb5ceSopenharmony_ci } 881d4afb5ceSopenharmony_ci 882d4afb5ceSopenharmony_ci /* there are no further items in the array */ 883d4afb5ceSopenharmony_ci 884d4afb5ceSopenharmony_ci js->offset = 0; 885d4afb5ceSopenharmony_ci lws_struct_pretty(js, &buf, &len); 886d4afb5ceSopenharmony_ci *buf++ = ']'; 887d4afb5ceSopenharmony_ci len--; 888d4afb5ceSopenharmony_ci goto up; 889d4afb5ceSopenharmony_ci } 890d4afb5ceSopenharmony_ci 891d4afb5ceSopenharmony_ci *written = olen - len; 892d4afb5ceSopenharmony_ci *buf = '\0'; /* convenience, a NUL after the official end */ 893d4afb5ceSopenharmony_ci 894d4afb5ceSopenharmony_ci return LSJS_RESULT_FINISH; 895d4afb5ceSopenharmony_ci} 896