/* handles JSON requests */ static void on_request_json(http_s *h) { http_set_header(h, HTTP_HEADER_CONTENT_TYPE, http_mimetype_find("json", 4)); FIOBJ json; /* create a new Hash to be serialized for every request */ FIOBJ hash = fiobj_hash_new2(1); fiobj_hash_set(hash, JSON_KEY, fiobj_dup(JSON_VALUE)); json = fiobj_obj2json(hash, 0); fiobj_free(hash); fio_str_info_s tmp = fiobj_obj2cstr(json); http_send_body(h, tmp.data, tmp.len); fiobj_free(json); }
/* routes a request to the correct handler */ static void route_perform(http_s *h) { /* add required Serevr header */ http_set_header(h, HTTP_HEADER_SERVER, fiobj_dup(HTTP_VALUE_SERVER)); /* collect path from hash map */ fio_str_info_s tmp_i = fiobj_obj2cstr(h->path); fio_str_s tmp = FIO_STR_INIT_EXISTING(tmp_i.data, tmp_i.len, 0); fio_router_handler_fn handler = fio_router_find(&routes, fio_str_hash(&tmp), tmp); /* forward request or send error */ if (handler) { handler(h); return; } http_send_error(h, 404); }
/** * Returns 1 if the key (Symbol) exists in the Hash, even if value is NULL. */ int fiobj_hash_haskey(const fiobj_s *hash, fiobj_s *sym) { if (hash->type != FIOBJ_T_HASH) { return 0; } uintptr_t hash_value = 0; if (sym->type == FIOBJ_T_SYMBOL) { hash_value = fiobj_sym_id(sym); } else if (FIOBJ_IS_STRING(sym)) { fio_cstr_s str = fiobj_obj2cstr(sym); hash_value = fiobj_sym_hash(str.value, str.len); } else { return 0; } fiobj_s *coup = fio_hash_find(obj2hash(hash), hash_value); if (!coup) return 0; return 1; }
/** * Creates a mutable empty Hash object. Use `fiobj_free` when done. * * Notice that these Hash objects are designed for smaller collections and * retain order of object insertion. */ fiobj_s *fiobj_hash_new(void) { fiobj_s *o = fiobj_alloc(sizeof(fiobj_hash_s)); if (!o) perror("ERROR: fiobj hash couldn't allocate memory"), exit(errno); *obj2hash(o) = (fiobj_hash_s){ .vtable = &FIOBJ_VTABLE_HASH, .mask = (HASH_INITIAL_CAPACITY - 1), .items = FIO_LS_INIT((obj2hash(o)->items)), .map.data = calloc(sizeof(map_info_s), HASH_INITIAL_CAPACITY), .map.capa = HASH_INITIAL_CAPACITY, }; if (!obj2hash(o)->map.data) perror("ERROR: fiobj hash couldn't allocate memory"), exit(errno); return o; } /** Returns the number of elements in the Hash. */ size_t fiobj_hash_count(const fiobj_s *hash) { if (!hash || hash->type != FIOBJ_T_HASH) return 0; return obj2hash(hash)->count; } /** * Sets a key-value pair in the Hash, duplicating the Symbol and **moving** * the ownership of the object to the Hash. * * Returns -1 on error. */ int fiobj_hash_set(fiobj_s *hash, fiobj_s *sym, fiobj_s *obj) { if (hash->type != FIOBJ_T_HASH) { fiobj_free(obj); return -1; } uintptr_t hash_value = 0; if (sym->type == FIOBJ_T_SYMBOL) { hash_value = fiobj_sym_id(sym); } else if (FIOBJ_IS_STRING(sym)) { fio_cstr_s str = fiobj_obj2cstr(sym); hash_value = fiobj_sym_hash(str.value, str.len); } else { fiobj_free((fiobj_s *)obj); return -1; } fiobj_s *coup = fiobj_couplet_alloc(sym, obj); fiobj_s *old = fio_hash_insert(obj2hash(hash), hash_value, coup); while (old == (void *)-1) { fiobj_hash_rehash(hash); old = fio_hash_insert(obj2hash(hash), hash_value, coup); // fprintf(stderr, "WARN: (fiobj Hash) collision limit reached" // " - forced rehashing\n"); } if (old) { fiobj_free(obj2couplet(old)->obj); obj2couplet(old)->obj = NULL; fiobj_couplet_dealloc(old); } return 0; } /** * Removes a key-value pair from the Hash, if it exists, returning the old * object (instead of freeing it). */ fiobj_s *fiobj_hash_remove(fiobj_s *hash, fiobj_s *sym) { if (hash->type != FIOBJ_T_HASH) { return 0; } uintptr_t hash_value = 0; if (sym->type == FIOBJ_T_SYMBOL) { hash_value = fiobj_sym_id(sym); } else if (FIOBJ_IS_STRING(sym)) { fio_cstr_s str = fiobj_obj2cstr(sym); hash_value = fiobj_sym_hash(str.value, str.len); } else { return NULL; } fiobj_s *coup = fio_hash_insert(obj2hash(hash), hash_value, NULL); if (!coup) return NULL; fiobj_s *ret = fiobj_couplet2obj(coup); obj2couplet(coup)->obj = NULL; fiobj_couplet_dealloc((fiobj_s *)coup); return ret; } /** * Deletes a key-value pair from the Hash, if it exists, freeing the * associated object. * * Returns -1 on type error or if the object never existed. */ int fiobj_hash_delete(fiobj_s *hash, fiobj_s *sym) { fiobj_s *obj = fiobj_hash_remove(hash, sym); if (!obj) return -1; fiobj_free(obj); return 0; }