--- a/ucx/cx/hash_key.h Sun Aug 31 14:39:13 2025 +0200 +++ b/ucx/cx/hash_key.h Sat Nov 08 23:06:11 2025 +0100 @@ -46,14 +46,17 @@ /** Internal structure for a key within a hash map. */ struct cx_hash_key_s { - /** The key data. */ + /** + * The key data. + * May be NULL when the hash is collision-free. + */ const void *data; /** * The key data length. */ size_t len; /** The hash value of the key data. */ - unsigned hash; + uint64_t hash; }; /** @@ -76,8 +79,45 @@ * @see cx_hash_key() */ cx_attr_nonnull -cx_attr_export -void cx_hash_murmur(CxHashKey *key); +CX_EXPORT void cx_hash_murmur(CxHashKey *key); + +/** + * Mixes up a 32-bit integer to be used as a hash. + * + * This function produces no collisions and has a good statistical distribution. + * + * @param x the integer + * @return the hash + */ +CX_EXPORT uint32_t cx_hash_u32(uint32_t x); + +/** + * Mixes up a 64-bit integer to be used as a hash. + * + * This function produces no collisions and has a good statistical distribution. + * + * @param x the integer + * @return the hash + */ +CX_EXPORT uint64_t cx_hash_u64(uint64_t x); + +/** + * Computes a hash key from a 32-bit integer. + * + * @param x the integer + * @return the hash key + */ +cx_attr_nodiscard +CX_EXPORT CxHashKey cx_hash_key_u32(uint32_t x); + +/** + * Computes a hash key from a 64-bit integer. + * + * @param x the integer + * @return the hash key + */ +cx_attr_nodiscard +CX_EXPORT CxHashKey cx_hash_key_u64(uint64_t x); /** * Computes a hash key from a string. @@ -87,10 +127,22 @@ * @param str the string * @return the hash key */ -cx_attr_nodiscard -cx_attr_cstr_arg(1) -cx_attr_export -CxHashKey cx_hash_key_str(const char *str); +cx_attr_nodiscard cx_attr_cstr_arg(1) +CX_EXPORT CxHashKey cx_hash_key_str(const char *str); + +/** + * Computes a hash key from a string. + * + * Use this function when the string is represented + * as an unsigned char array. + * + * The string needs to be zero-terminated. + * + * @param str the string + * @return the hash key + */ +cx_attr_nodiscard cx_attr_cstr_arg(1) +CX_EXPORT CxHashKey cx_hash_key_ustr(const unsigned char *str); /** * Computes a hash key from a byte array. @@ -99,13 +151,8 @@ * @param len the length * @return the hash key */ -cx_attr_nodiscard -cx_attr_access_r(1, 2) -cx_attr_export -CxHashKey cx_hash_key_bytes( - const unsigned char *bytes, - size_t len -); +cx_attr_nodiscard cx_attr_access_r(1, 2) +CX_EXPORT CxHashKey cx_hash_key_bytes(const unsigned char *bytes, size_t len); /** * Computes a hash key for an arbitrary object. @@ -115,16 +162,21 @@ * used for data exchange with different machines. * * @param obj a pointer to an arbitrary object - * @param len the length of object in memory + * @param len the length of the object in memory * @return the hash key */ cx_attr_nodiscard cx_attr_access_r(1, 2) -cx_attr_export -CxHashKey cx_hash_key( - const void *obj, - size_t len -); +CX_EXPORT CxHashKey cx_hash_key(const void *obj, size_t len); + +/** + * Computes a hash key from a UCX string. + * + * @param str the string + * @return the hash key + */ +cx_attr_nodiscard +CX_EXPORT CxHashKey cx_hash_key_cxstr(cxstring str); /** * Computes a hash key from a UCX string. @@ -133,20 +185,91 @@ * @return the hash key */ cx_attr_nodiscard -static inline CxHashKey cx_hash_key_cxstr(cxstring str) { - return cx_hash_key(str.ptr, str.length); -} +CX_EXPORT CxHashKey cx_hash_key_mutstr(cxmutstr str); /** - * Computes a hash key from a UCX string. + * The identity function for the CX_HASH_KEY() macro. + * You should never need to use this manually. + * + * @param key the key + * @return a copy of the key + */ +cx_attr_nodiscard +CX_INLINE CxHashKey cx_hash_key_identity(CxHashKey key) { + return key; +} + +#ifndef __cplusplus +/** + * Creates a hash key from any of the supported types with implicit length. + * + * Does nothing when passing a CxHashkey. + * + * Supported types are UCX strings, zero-terminated C strings, + * and 32-bit or 64-bit unsigned integers. * - * @param str (@c cxstring or @c cxmutstr) the string - * @return (@c CxHashKey) the hash key + * @param key the key data + * @returns the @c CxHashKey */ -#define cx_hash_key_cxstr(str) cx_hash_key_cxstr(cx_strcast(str)) +#define CX_HASH_KEY(key) _Generic((key), \ + CxHashKey: cx_hash_key_identity, \ + cxstring: cx_hash_key_cxstr, \ + cxmutstr: cx_hash_key_mutstr, \ + char*: cx_hash_key_str, \ + const char*: cx_hash_key_str, \ + unsigned char*: cx_hash_key_ustr, \ + const unsigned char*: cx_hash_key_ustr, \ + uint32_t: cx_hash_key_u32, \ + uint64_t: cx_hash_key_u64) \ + (key) +#endif // __cplusplus + +/** + * Compare function for hash keys. + * + * The pointers are untyped to be compatible with the cx_compare_func signature. + * + * @param left (@c CxHashKey*) the first key + * @param right (@c CxHashKey*) the second key + * @return zero when the keys equal, non-zero when they differ + */ +cx_attr_nodiscard cx_attr_nonnull +CX_EXPORT int cx_hash_key_cmp(const void *left, const void *right); #ifdef __cplusplus } // extern "C" + +// ---------------------------------------------------------- +// Overloads of CX_HASH_KEY (the C++ version of a _Generic) +// ---------------------------------------------------------- + +CX_CPPDECL CxHashKey CX_HASH_KEY(CxHashKey key) { + return key; +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(cxstring str) { + return cx_hash_key_cxstr(str); +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(cxmutstr str) { + return cx_hash_key_mutstr(str); +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(const char *str) { + return cx_hash_key_str(str); +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(const unsigned char *str) { + return cx_hash_key_ustr(str); +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(uint32_t key) { + return cx_hash_key_u32(key); +} + +CX_CPPDECL CxHashKey CX_HASH_KEY(uint64_t key) { + return cx_hash_key_u64(key); +} #endif #endif // UCX_HASH_KEY_H