Example #1
0
/* 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);
}
Example #2
0
/* 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);
}
Example #3
0
/**
 * 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;
}
Example #4
0
/**
 * 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;
}