11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) 2023 Brad House
41cb0ef41Sopenharmony_ci *
51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
111cb0ef41Sopenharmony_ci *
121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
141cb0ef41Sopenharmony_ci * Software.
151cb0ef41Sopenharmony_ci *
161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
221cb0ef41Sopenharmony_ci * SOFTWARE.
231cb0ef41Sopenharmony_ci *
241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_ci#include "ares_setup.h"
271cb0ef41Sopenharmony_ci#include "ares.h"
281cb0ef41Sopenharmony_ci#include "ares_private.h"
291cb0ef41Sopenharmony_ci#include "ares__htable.h"
301cb0ef41Sopenharmony_ci#include "ares__htable_szvp.h"
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_cistruct ares__htable_szvp {
331cb0ef41Sopenharmony_ci  ares__htable_szvp_val_free_t free_val;
341cb0ef41Sopenharmony_ci  ares__htable_t              *hash;
351cb0ef41Sopenharmony_ci};
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_citypedef struct {
381cb0ef41Sopenharmony_ci  size_t               key;
391cb0ef41Sopenharmony_ci  void                *val;
401cb0ef41Sopenharmony_ci  ares__htable_szvp_t *parent;
411cb0ef41Sopenharmony_ci} ares__htable_szvp_bucket_t;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_civoid ares__htable_szvp_destroy(ares__htable_szvp_t *htable)
441cb0ef41Sopenharmony_ci{
451cb0ef41Sopenharmony_ci  if (htable == NULL) {
461cb0ef41Sopenharmony_ci    return;
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  ares__htable_destroy(htable->hash);
501cb0ef41Sopenharmony_ci  ares_free(htable);
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cistatic unsigned int hash_func(const void *key, unsigned int seed)
541cb0ef41Sopenharmony_ci{
551cb0ef41Sopenharmony_ci  const size_t *arg = key;
561cb0ef41Sopenharmony_ci  return ares__htable_hash_FNV1a((const unsigned char *)arg, sizeof(*arg),
571cb0ef41Sopenharmony_ci                                 seed);
581cb0ef41Sopenharmony_ci}
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cistatic const void *bucket_key(const void *bucket)
611cb0ef41Sopenharmony_ci{
621cb0ef41Sopenharmony_ci  const ares__htable_szvp_bucket_t *arg = bucket;
631cb0ef41Sopenharmony_ci  return &arg->key;
641cb0ef41Sopenharmony_ci}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cistatic void bucket_free(void *bucket)
671cb0ef41Sopenharmony_ci{
681cb0ef41Sopenharmony_ci  ares__htable_szvp_bucket_t *arg = bucket;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  if (arg->parent->free_val) {
711cb0ef41Sopenharmony_ci    arg->parent->free_val(arg->val);
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  ares_free(arg);
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_cistatic ares_bool_t key_eq(const void *key1, const void *key2)
781cb0ef41Sopenharmony_ci{
791cb0ef41Sopenharmony_ci  const size_t *k1 = key1;
801cb0ef41Sopenharmony_ci  const size_t *k2 = key2;
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  if (*k1 == *k2) {
831cb0ef41Sopenharmony_ci    return ARES_TRUE;
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  return ARES_FALSE;
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciares__htable_szvp_t *
901cb0ef41Sopenharmony_ci  ares__htable_szvp_create(ares__htable_szvp_val_free_t val_free)
911cb0ef41Sopenharmony_ci{
921cb0ef41Sopenharmony_ci  ares__htable_szvp_t *htable = ares_malloc(sizeof(*htable));
931cb0ef41Sopenharmony_ci  if (htable == NULL) {
941cb0ef41Sopenharmony_ci    goto fail;
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  htable->hash =
981cb0ef41Sopenharmony_ci    ares__htable_create(hash_func, bucket_key, bucket_free, key_eq);
991cb0ef41Sopenharmony_ci  if (htable->hash == NULL) {
1001cb0ef41Sopenharmony_ci    goto fail;
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  htable->free_val = val_free;
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  return htable;
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cifail:
1081cb0ef41Sopenharmony_ci  if (htable) {
1091cb0ef41Sopenharmony_ci    ares__htable_destroy(htable->hash);
1101cb0ef41Sopenharmony_ci    ares_free(htable);
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci  return NULL;
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ciares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key,
1161cb0ef41Sopenharmony_ci                                     void *val)
1171cb0ef41Sopenharmony_ci{
1181cb0ef41Sopenharmony_ci  ares__htable_szvp_bucket_t *bucket = NULL;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  if (htable == NULL) {
1211cb0ef41Sopenharmony_ci    goto fail;
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  bucket = ares_malloc(sizeof(*bucket));
1251cb0ef41Sopenharmony_ci  if (bucket == NULL) {
1261cb0ef41Sopenharmony_ci    goto fail;
1271cb0ef41Sopenharmony_ci  }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  bucket->parent = htable;
1301cb0ef41Sopenharmony_ci  bucket->key    = key;
1311cb0ef41Sopenharmony_ci  bucket->val    = val;
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  if (!ares__htable_insert(htable->hash, bucket)) {
1341cb0ef41Sopenharmony_ci    goto fail;
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  return ARES_TRUE;
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_cifail:
1401cb0ef41Sopenharmony_ci  if (bucket) {
1411cb0ef41Sopenharmony_ci    ares_free(bucket);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  return ARES_FALSE;
1441cb0ef41Sopenharmony_ci}
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ciares_bool_t ares__htable_szvp_get(const ares__htable_szvp_t *htable, size_t key,
1471cb0ef41Sopenharmony_ci                                  void **val)
1481cb0ef41Sopenharmony_ci{
1491cb0ef41Sopenharmony_ci  ares__htable_szvp_bucket_t *bucket = NULL;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  if (val) {
1521cb0ef41Sopenharmony_ci    *val = NULL;
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  if (htable == NULL) {
1561cb0ef41Sopenharmony_ci    return ARES_FALSE;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  bucket = ares__htable_get(htable->hash, &key);
1601cb0ef41Sopenharmony_ci  if (bucket == NULL) {
1611cb0ef41Sopenharmony_ci    return ARES_FALSE;
1621cb0ef41Sopenharmony_ci  }
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  if (val) {
1651cb0ef41Sopenharmony_ci    *val = bucket->val;
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci  return ARES_TRUE;
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_civoid *ares__htable_szvp_get_direct(const ares__htable_szvp_t *htable,
1711cb0ef41Sopenharmony_ci                                   size_t                     key)
1721cb0ef41Sopenharmony_ci{
1731cb0ef41Sopenharmony_ci  void *val = NULL;
1741cb0ef41Sopenharmony_ci  ares__htable_szvp_get(htable, key, &val);
1751cb0ef41Sopenharmony_ci  return val;
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ciares_bool_t ares__htable_szvp_remove(ares__htable_szvp_t *htable, size_t key)
1791cb0ef41Sopenharmony_ci{
1801cb0ef41Sopenharmony_ci  if (htable == NULL) {
1811cb0ef41Sopenharmony_ci    return ARES_FALSE;
1821cb0ef41Sopenharmony_ci  }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  return ares__htable_remove(htable->hash, &key);
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_cisize_t ares__htable_szvp_num_keys(const ares__htable_szvp_t *htable)
1881cb0ef41Sopenharmony_ci{
1891cb0ef41Sopenharmony_ci  if (htable == NULL) {
1901cb0ef41Sopenharmony_ci    return 0;
1911cb0ef41Sopenharmony_ci  }
1921cb0ef41Sopenharmony_ci  return ares__htable_num_keys(htable->hash);
1931cb0ef41Sopenharmony_ci}
194