static void json_delete_object(json_object_t *object) { hashtable_close(&object->hashtable); free(object); }
void verr_cleanup() { verr_thread_cleanup(); hashtable_close(providers); }
void hashtable_destroy(hashtable_t *hashtable) { hashtable_close(hashtable); free(hashtable); }
void pc_map_close(pc_map_t *map) { // TODO: iterate and release listner lists hashtable_close(&map->table); }
static int unpack_object(scanner_t *s, json_t *root, va_list *ap) { int ret = -1; int strict = 0; /* Use a set (emulated by a hashtable) to check that all object keys are accessed. Checking that the correct number of keys were accessed is not enough, as the same key can be unpacked multiple times. */ hashtable_t key_set; if(hashtable_init(&key_set)) { set_error(s, "<internal>", "Out of memory"); return -1; } if(root && !json_is_object(root)) { set_error(s, "<validation>", "Expected object, got %s", type_name(root)); goto out; } next_token(s); while(s->token != '}') { const char *key; json_t *value; int opt = 0; if(strict != 0) { set_error(s, "<format>", "Expected '}' after '%c', got '%c'", (strict == 1 ? '!' : '*'), s->token); goto out; } if(!s->token) { set_error(s, "<format>", "Unexpected end of format string"); goto out; } if(s->token == '!' || s->token == '*') { strict = (s->token == '!' ? 1 : -1); next_token(s); continue; } if(s->token != 's') { set_error(s, "<format>", "Expected format 's', got '%c'", s->token); goto out; } key = va_arg(*ap, const char *); if(!key) { set_error(s, "<args>", "NULL object key"); goto out; } next_token(s); if(s->token == '?') { opt = 1; next_token(s); } if(!root) { /* skipping */ value = NULL; } else { value = json_object_get(root, key); if(!value && !opt) { set_error(s, "<validation>", "Object item not found: %s", key); goto out; } } if(unpack(s, value, ap)) goto out; hashtable_set(&key_set, key, 0, json_null()); next_token(s); } if(strict == 0 && (s->flags & JSON_STRICT)) strict = 1; if(root && strict == 1 && key_set.size != json_object_size(root)) { long diff = (long)json_object_size(root) - (long)key_set.size; set_error(s, "<validation>", "%li object item(s) left unpacked", diff); goto out; } ret = 0; out: hashtable_close(&key_set); return ret; }