--- a/ucx/cx/hash_key.h Wed Dec 31 12:37:09 2025 +0100 +++ b/ucx/cx/hash_key.h Wed Dec 31 16:40:12 2025 +0100 @@ -40,10 +40,6 @@ #include "common.h" #include "string.h" -#ifdef __cplusplus -extern "C" { -#endif - /** Internal structure for a key within a hash map. */ struct cx_hash_key_s { /** @@ -78,8 +74,8 @@ * @param key the key, the hash shall be computed for * @see cx_hash_key() */ -cx_attr_nonnull -CX_EXPORT void cx_hash_murmur(CxHashKey *key); +CX_EXTERN CX_NONNULL +void cx_hash_murmur(CxHashKey *key); /** * Mixes up a 32-bit integer to be used as a hash. @@ -89,7 +85,13 @@ * @param x the integer * @return the hash */ -CX_EXPORT uint32_t cx_hash_u32(uint32_t x); +CX_INLINE +uint32_t cx_hash_u32(uint32_t x) { + x = ((x >> 16) ^ x) * 0x45d9f3bu; + x = ((x >> 16) ^ x) * 0x45d9f3bu; + x = (x >> 16) ^ x; + return x; +} /** * Mixes up a 64-bit integer to be used as a hash. @@ -99,7 +101,27 @@ * @param x the integer * @return the hash */ -CX_EXPORT uint64_t cx_hash_u64(uint64_t x); +CX_INLINE +uint64_t cx_hash_u64(uint64_t x){ + x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9); + x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb); + x = x ^ (x >> 31); + return x; +} + +/** + * Computes a hash key for an arbitrary object. + * + * The computation uses the in-memory representation that might not be + * the same on different platforms. Therefore, this hash should not be + * used for data exchange with different machines. + * + * @param obj a pointer to an arbitrary object + * @param len the length of the object in memory + * @return the hash key + */ +CX_EXTERN CX_NODISCARD CX_ACCESS_R(1, 2) +CxHashKey cx_hash_key(const void *obj, size_t len); /** * Computes a hash key from a 32-bit integer. @@ -107,8 +129,14 @@ * @param x the integer * @return the hash key */ -cx_attr_nodiscard -CX_EXPORT CxHashKey cx_hash_key_u32(uint32_t x); +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_u32(uint32_t x) { + CxHashKey key; + key.data = NULL; + key.len = 0; + key.hash = cx_hash_u32(x); + return key; +} /** * Computes a hash key from a 64-bit integer. @@ -116,8 +144,14 @@ * @param x the integer * @return the hash key */ -cx_attr_nodiscard -CX_EXPORT CxHashKey cx_hash_key_u64(uint64_t x); +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_u64(uint64_t x) { + CxHashKey key; + key.data = NULL; + key.len = 0; + key.hash = cx_hash_u64(x); + return key; +} /** * Computes a hash key from a string. @@ -127,8 +161,10 @@ * @param str the string * @return the hash key */ -cx_attr_nodiscard cx_attr_cstr_arg(1) -CX_EXPORT CxHashKey cx_hash_key_str(const char *str); +CX_NODISCARD CX_CSTR_ARG(1) CX_INLINE +CxHashKey cx_hash_key_str(const char *str) { + return cx_hash_key((const void*)str, str == NULL ? 0 : strlen(str)); +} /** * Computes a hash key from a string. @@ -141,8 +177,10 @@ * @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); +CX_NODISCARD CX_CSTR_ARG(1) CX_INLINE +CxHashKey cx_hash_key_ustr(const unsigned char *str) { + return cx_hash_key((const void*)str, str == NULL ? 0 : strlen((const char*)str)); +} /** * Computes a hash key from a byte array. @@ -151,23 +189,21 @@ * @param len the length * @return the hash key */ -cx_attr_nodiscard cx_attr_access_r(1, 2) -CX_EXPORT CxHashKey cx_hash_key_bytes(const unsigned char *bytes, size_t len); +CX_NODISCARD CX_ACCESS_R(1, 2) CX_INLINE +CxHashKey cx_hash_key_bytes(const unsigned char *bytes, size_t len) { + return cx_hash_key((const void*)bytes, len); +} /** - * Computes a hash key for an arbitrary object. + * Computes a hash key from a UCX string. * - * The computation uses the in-memory representation that might not be - * the same on different platforms. Therefore, this hash should not be - * used for data exchange with different machines. - * - * @param obj a pointer to an arbitrary object - * @param len the length of the object in memory + * @param str the string * @return the hash key */ -cx_attr_nodiscard -cx_attr_access_r(1, 2) -CX_EXPORT CxHashKey cx_hash_key(const void *obj, size_t len); +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_cxstr(cxstring str) { + return cx_hash_key((void*)str.ptr, str.length); +} /** * Computes a hash key from a UCX string. @@ -175,35 +211,40 @@ * @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. - * - * @param str the string - * @return the hash key - */ -cx_attr_nodiscard -CX_EXPORT CxHashKey cx_hash_key_mutstr(cxmutstr str); +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_mutstr(cxmutstr str) { + return cx_hash_key((void*)str.ptr, str.length); +} /** * 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 + * @return a copy of the key (not the data) */ -cx_attr_nodiscard -CX_INLINE CxHashKey cx_hash_key_identity(CxHashKey key) { +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_identity(CxHashKey key) { return key; } +/** + * The dereference function for the CX_HASH_KEY() macro. + * You should never need to use this manually. + * + * @param key a pointer to a key + * @return a copy of the key (not the data) + */ +CX_NODISCARD CX_INLINE +CxHashKey cx_hash_key_deref(const 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. + * Does nothing when passing a CxHashKey and dereferences CxHashKey pointers. * * Supported types are UCX strings, zero-terminated C strings, * and 32-bit or 64-bit unsigned integers. @@ -212,6 +253,8 @@ * @returns the @c CxHashKey */ #define CX_HASH_KEY(key) _Generic((key), \ + CxHashKey*: cx_hash_key_deref, \ + const CxHashKey*: cx_hash_key_deref, \ CxHashKey: cx_hash_key_identity, \ cxstring: cx_hash_key_cxstr, \ cxmutstr: cx_hash_key_mutstr, \ @@ -233,12 +276,19 @@ * @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); +CX_EXTERN CX_NODISCARD CX_NONNULL +int cx_hash_key_cmp(const void *left, const void *right); + +/** + * Interprets the key data as a string and returns it. + * + * @param key the key + * @return the key data as a string + */ +CX_EXTERN +cxstring cx_hash_key_as_string(const CxHashKey *key); #ifdef __cplusplus -} // extern "C" - // ---------------------------------------------------------- // Overloads of CX_HASH_KEY (the C++ version of a _Generic) // ---------------------------------------------------------- @@ -247,6 +297,10 @@ return key; } +CX_CPPDECL CxHashKey CX_HASH_KEY(const CxHashKey *key) { + return *key; +} + CX_CPPDECL CxHashKey CX_HASH_KEY(cxstring str) { return cx_hash_key_cxstr(str); }