Skip to content

Commit

Permalink
Librhash: Support extended hash identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
rhash committed Dec 23, 2024
1 parent ad43c5a commit 04caf13
Show file tree
Hide file tree
Showing 11 changed files with 255 additions and 120 deletions.
7 changes: 5 additions & 2 deletions calc_sums.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ extern "C" {
#endif

/* Hash function identifiers and bit masks */
#define bit64_to_hash_id(bit64) ((unsigned)(bit64))
#define hash_id_to_bit64(hash_id) ((uint64_t)(hash_id))
#define bit64_to_hash_id(bit64) ((unsigned)RHASH_EXTENDED_BIT ^ get_ctz64(bit64))
#define hash_id_to_bit64(hash_id) ((hash_id) & RHASH_EXTENDED_BIT ? \
(uint64_t)1 << (unsigned)((hash_id) & ~RHASH_EXTENDED_BIT): (uint64_t)(hash_id))
#define hash_id_to_extended(hash_id) ((hash_id) & RHASH_EXTENDED_BIT ? hash_id : \
(unsigned)RHASH_EXTENDED_BIT ^ get_ctz(hash_id))

int hash_mask_to_hash_ids(uint64_t hash_mask, unsigned max_count,
unsigned* hash_ids, unsigned* out_count);
Expand Down
22 changes: 21 additions & 1 deletion common_func.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,12 +440,32 @@ void* rhash_realloc(void* mem, size_t size, const char* srcfile, int srcline)
unsigned get_ctz(unsigned x)
{
/* array for conversion to bit position */
static unsigned char bit_pos[32] = {
static unsigned bit_pos[32] = {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
return bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];
}
/**
* Returns index of the trailing bit of a 64-bit number.
* This is a plain C equivalent for GCC __builtin_ctzll() bit scan.
* Original author: Matt Taylor (2003).
*
* @param x the number to process
* @return zero-based index of the trailing bit
*/
unsigned get_ctz64(uint64_t x)
{
/* array for conversion to bit position */
static unsigned bit_pos[64] = {
63, 30, 3, 32, 59, 14, 11, 33, 60, 24, 50, 9, 55, 19, 21, 34,
61, 29, 2, 53, 51, 23, 41, 18, 56, 28, 1, 43, 46, 27, 0, 35,
62, 31, 58, 4, 5, 49, 54, 6, 15, 52, 12, 40, 7, 42, 45, 16,
25, 57, 48, 13, 10, 39, 8, 44, 20, 47, 38, 22, 17, 37, 36, 26
};
uint32_t folded = (uint32_t)(((x - 1) >> 32) ^ (x - 1));
return bit_pos[folded * 0x78291ACF >> 26];
}
#endif

/*=========================================================================
Expand Down
4 changes: 3 additions & 1 deletion common_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ wchar_t* rhash_wcsdup(const wchar_t* str, const char* srcfile, int srcline);
(defined(__clang__) && __has_builtin(__builtin_ctz))
/* macro if GCC >= 3.4 or has clang __builtin_ctz() */
# define get_ctz(x) __builtin_ctz(x)
# define get_ctz64(x) __builtin_ctzll(x)
#else
unsigned get_ctz(unsigned); /* define as function */
unsigned get_ctz(unsigned);
unsigned get_ctz64(uint64_t);
#endif

/* vector functions */
Expand Down
45 changes: 26 additions & 19 deletions hash_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef struct print_item
{
struct print_item* next;
unsigned flags;
unsigned hash_mask;
unsigned hash_id;
unsigned width;
const char* data;
} print_item;
Expand All @@ -84,15 +84,15 @@ static print_item* parse_percent_item(const char** str);
* Allocate new print_item.
*
* @param flags the print_item flags
* @param hash_mask optional hash_mask
* @param hash_id optional hash_id
* @param data optional string to store
* @return allocated print_item
*/
static print_item* new_print_item(unsigned flags, uint64_t hash_mask, const char* data)
static print_item* new_print_item(unsigned flags, unsigned hash_id, const char* data)
{
print_item* item = (print_item*)rsh_malloc(sizeof(print_item));
item->flags = flags;
item->hash_mask = hash_mask;
item->hash_id = hash_id;
item->width = 0;
item->data = (data ? rsh_strdup(data) : NULL);
item->next = NULL;
Expand Down Expand Up @@ -212,8 +212,13 @@ print_item* parse_print_string(const char* format, uint64_t* hash_mask)
if (esc_head->flags != esc_tail->flags)
esc_head->flags |= FLAG_HAS_MISC_PARTS;
}
if (item->hash_mask)
*hash_mask |= item->hash_mask;
if ((item->flags & ~PRINT_FLAGS_ALL) == PRINT_ED2K_LINK) {
static const uint64_t ed2k_aich_hash_mask =
hash_id_to_bit64(RHASH_ED2K) | hash_id_to_bit64(RHASH_AICH);
*hash_mask |= ed2k_aich_hash_mask;
} else if (item->hash_id) {
*hash_mask |= hash_id_to_bit64(item->hash_id);
}
}
}
if (p > buf || (!*format && list == NULL && item == NULL)) {
Expand Down Expand Up @@ -314,7 +319,7 @@ print_item* parse_percent_item(const char** str)
{
const char* format = *str;
const char* p = NULL;
uint64_t hash_mask = 0;
unsigned hash_id = 0;
unsigned modifier_flags = 0;
int id_found = 0;
int width = 0;
Expand Down Expand Up @@ -362,8 +367,8 @@ print_item* parse_percent_item(const char** str)
for (; isalnum((unsigned char)*p) || (*p == '-'); p++);
if (*p == '}') {
unsigned flags = 0;
hash_mask = printf_name_to_id(format + 1, p - (format + 1), &flags);
if (hash_mask || (flags & PRINT_FLAG_URLENCODE) || flags == PRINT_MTIME) {
hash_id = printf_name_to_id(format + 1, p - (format + 1), &flags);
if (hash_id || (flags & PRINT_FLAG_URLENCODE) || flags == PRINT_MTIME) {
/* set uppercase flag if the first letter of printf-entity is uppercase */
modifier_flags |= flags | (format[1] & 0x20 ? 0 : PRINT_FLAG_UPPERCASE);
format = p;
Expand All @@ -381,16 +386,12 @@ print_item* parse_percent_item(const char** str)
/* look for a known token */
if (upper && (p = strchr(short_hash, upper))) {
assert( (p - short_hash) < (int)(sizeof(hash_ids) / sizeof(unsigned)) );
hash_mask = hash_id_to_bit64(hash_ids[p - short_hash]);
hash_id = hash_ids[p - short_hash];
modifier_flags |= (*format & 0x20 ? 0 : PRINT_FLAG_UPPERCASE);
}
else if ((p = strchr(short_other, *format))) {
static const uint64_t ed2k_aich_hash_mask =
hash_id_to_bit64(RHASH_ED2K) | hash_id_to_bit64(RHASH_AICH);
assert( (p - short_other) < (int)(sizeof(other_flags) / sizeof(unsigned)) );
modifier_flags |= other_flags[p - short_other];
if ((modifier_flags & ~PRINT_FLAGS_ALL) == PRINT_ED2K_LINK)
hash_mask = ed2k_aich_hash_mask;
} else if ((modifier_flags & PRINT_FLAG_URLENCODE) != 0) {
/* handle legacy token: '%u' -> '%uf' */
modifier_flags |= PRINT_BASENAME;
Expand All @@ -399,7 +400,7 @@ print_item* parse_percent_item(const char** str)
return 0; /* no valid token found */
}
}
item = new_print_item(modifier_flags, hash_mask, NULL);
item = new_print_item(modifier_flags, hash_id, NULL);
item->width = width;
*str = ++format;
return item;
Expand Down Expand Up @@ -494,6 +495,13 @@ static int print_time64(FILE* out, uint64_t time64, int sfv_format)
return PRINTF_RES(rsh_fprintf(out, format, d[0], d[1], d[2], d[3], d[4], d[5]));
}

static int is_gost94(unsigned hash_id)
{
static unsigned gost94_id = hash_id_to_extended(RHASH_GOST94);
static unsigned gost94_cryptopro_id = hash_id_to_extended(RHASH_GOST94_CRYPTOPRO);
return (hash_id == gost94_id || hash_id == gost94_cryptopro_id);
}

/**
* Print formatted file information to the given output stream.
*
Expand Down Expand Up @@ -522,17 +530,16 @@ int print_line(FILE* out, unsigned out_mode, print_item* list, struct file_info*

/* output a hash function digest */
if (!print_type) {
unsigned hash_id = bit64_to_hash_id(list->hash_mask);
int print_flags = (list->flags & PRINT_FLAG_UPPERCASE ? RHPR_UPPERCASE : 0)
| (list->flags & PRINT_FLAG_RAW ? RHPR_RAW : 0)
| (list->flags & PRINT_FLAG_BASE32 ? RHPR_BASE32 : 0)
| (list->flags & PRINT_FLAG_BASE64 ? RHPR_BASE64 : 0)
| (list->flags & PRINT_FLAG_HEX ? RHPR_HEX : 0)
| (list->flags & PRINT_FLAG_URLENCODE ? RHPR_URLENCODE : 0);
if ((hash_id == RHASH_GOST94 || hash_id == RHASH_GOST94_CRYPTOPRO) && (opt.flags & OPT_GOST_REVERSE))
if ((opt.flags & OPT_GOST_REVERSE) && is_gost94(list->hash_id))
print_flags |= RHPR_REVERSE;
assert(hash_id != 0);
len = rhash_print(buffer, info->rctx, hash_id, print_flags);
assert(list->hash_id != 0);
len = rhash_print(buffer, info->rctx, list->hash_id, print_flags);
assert(len < sizeof(buffer));
/* output the hash, continue on success */
if (rsh_fwrite(buffer, 1, len, out) == len || errno == 0)
Expand Down
110 changes: 62 additions & 48 deletions librhash/algorithms.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,37 +75,37 @@ static void rhash_crc32c_init(uint32_t* crc32);
static void rhash_crc32c_update(uint32_t* crc32, const unsigned char* msg, size_t size);
static void rhash_crc32c_final(uint32_t* crc32, unsigned char* result);

rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" };
rhash_info info_crc32c = { RHASH_CRC32C, F_BE32, 4, "CRC32C", "crc32c" };
rhash_info info_md4 = { RHASH_MD4, F_LE32, 16, "MD4", "md4" };
rhash_info info_md5 = { RHASH_MD5, F_LE32, 16, "MD5", "md5" };
rhash_info info_sha1 = { RHASH_SHA1, F_BE32, 20, "SHA1", "sha1" };
rhash_info info_tiger = { RHASH_TIGER, F_LE64, 24, "TIGER", "tiger" };
rhash_info info_tth = { RHASH_TTH, F_BS32 | F_SPCEXP, 24, "TTH", "tree:tiger" };
rhash_info info_btih = { RHASH_BTIH, F_SPCEXP, 20, "BTIH", "btih" };
rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" };
rhash_info info_aich = { RHASH_AICH, F_BS32 | F_SPCEXP, 20, "AICH", "aich" };
rhash_info info_whirlpool = { RHASH_WHIRLPOOL, F_BE64, 64, "WHIRLPOOL", "whirlpool" };
rhash_info info_rmd160 = { RHASH_RIPEMD160, F_LE32, 20, "RIPEMD-160", "ripemd160" };
rhash_info info_gost12_256 = { RHASH_GOST12_256, F_LE64, 32, "GOST12-256", "gost12-256" };
rhash_info info_gost12_512 = { RHASH_GOST12_512, F_LE64, 64, "GOST12-512", "gost12-512" };
rhash_info info_gost94 = { RHASH_GOST94, F_LE32, 32, "GOST94", "gost94" };
rhash_info info_gost94pro = { RHASH_GOST94_CRYPTOPRO, F_LE32, 32, "GOST94-CRYPTOPRO", "gost94-cryptopro" };
rhash_info info_has160 = { RHASH_HAS160, F_LE32, 20, "HAS-160", "has160" };
rhash_info info_snf128 = { RHASH_SNEFRU128, F_BE32, 16, "SNEFRU-128", "snefru128" };
rhash_info info_snf256 = { RHASH_SNEFRU256, F_BE32, 32, "SNEFRU-256", "snefru256" };
rhash_info info_sha224 = { RHASH_SHA224, F_BE32, 28, "SHA-224", "sha224" };
rhash_info info_sha256 = { RHASH_SHA256, F_BE32, 32, "SHA-256", "sha256" };
rhash_info info_sha384 = { RHASH_SHA384, F_BE64, 48, "SHA-384", "sha384" };
rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" };
rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" };
rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" };
rhash_info info_blake2s = { RHASH_BLAKE2S, F_LE32, 32, "BLAKE2S", "blake2s" };
rhash_info info_blake2b = { RHASH_BLAKE2B, F_LE64, 64, "BLAKE2B", "blake2b" };
rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" };
rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" };
rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" };
rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" };
rhash_info info_crc32 = { EXTENDED_HASH_ID(0), F_BE32, 4, "CRC32", "crc32" };
rhash_info info_crc32c = { EXTENDED_HASH_ID(26), F_BE32, 4, "CRC32C", "crc32c" };
rhash_info info_md4 = { EXTENDED_HASH_ID(1), F_LE32, 16, "MD4", "md4" };
rhash_info info_md5 = { EXTENDED_HASH_ID(2), F_LE32, 16, "MD5", "md5" };
rhash_info info_sha1 = { EXTENDED_HASH_ID(3), F_BE32, 20, "SHA1", "sha1" };
rhash_info info_tiger = { EXTENDED_HASH_ID(4), F_LE64, 24, "TIGER", "tiger" };
rhash_info info_tth = { EXTENDED_HASH_ID(5), F_BS32 | F_SPCEXP, 24, "TTH", "tree:tiger" };
rhash_info info_btih = { EXTENDED_HASH_ID(6), F_SPCEXP, 20, "BTIH", "btih" };
rhash_info info_ed2k = { EXTENDED_HASH_ID(7), F_LE32, 16, "ED2K", "ed2k" };
rhash_info info_aich = { EXTENDED_HASH_ID(8), F_BS32 | F_SPCEXP, 20, "AICH", "aich" };
rhash_info info_whirlpool = { EXTENDED_HASH_ID(9), F_BE64, 64, "WHIRLPOOL", "whirlpool" };
rhash_info info_rmd160 = { EXTENDED_HASH_ID(10), F_LE32, 20, "RIPEMD-160", "ripemd160" };
rhash_info info_gost94 = { EXTENDED_HASH_ID(11), F_LE32, 32, "GOST94", "gost94" };
rhash_info info_gost94pro = { EXTENDED_HASH_ID(12), F_LE32, 32, "GOST94-CRYPTOPRO", "gost94-cryptopro" };
rhash_info info_has160 = { EXTENDED_HASH_ID(13), F_LE32, 20, "HAS-160", "has160" };
rhash_info info_gost12_256 = { EXTENDED_HASH_ID(14), F_LE64, 32, "GOST12-256", "gost12-256" };
rhash_info info_gost12_512 = { EXTENDED_HASH_ID(15), F_LE64, 64, "GOST12-512", "gost12-512" };
rhash_info info_sha224 = { EXTENDED_HASH_ID(16), F_BE32, 28, "SHA-224", "sha224" };
rhash_info info_sha256 = { EXTENDED_HASH_ID(17), F_BE32, 32, "SHA-256", "sha256" };
rhash_info info_sha384 = { EXTENDED_HASH_ID(18), F_BE64, 48, "SHA-384", "sha384" };
rhash_info info_sha512 = { EXTENDED_HASH_ID(19), F_BE64, 64, "SHA-512", "sha512" };
rhash_info info_edr256 = { EXTENDED_HASH_ID(20), F_LE32, 32, "EDON-R256", "edon-r256" };
rhash_info info_edr512 = { EXTENDED_HASH_ID(21), F_LE64, 64, "EDON-R512", "edon-r512" };
rhash_info info_sha3_224 = { EXTENDED_HASH_ID(22), F_LE64, 28, "SHA3-224", "sha3-224" };
rhash_info info_sha3_256 = { EXTENDED_HASH_ID(23), F_LE64, 32, "SHA3-256", "sha3-256" };
rhash_info info_sha3_384 = { EXTENDED_HASH_ID(24), F_LE64, 48, "SHA3-384", "sha3-384" };
rhash_info info_sha3_512 = { EXTENDED_HASH_ID(25), F_LE64, 64, "SHA3-512", "sha3-512" };
rhash_info info_snf128 = { EXTENDED_HASH_ID(27), F_BE32, 16, "SNEFRU-128", "snefru128" };
rhash_info info_snf256 = { EXTENDED_HASH_ID(28), F_BE32, 32, "SNEFRU-256", "snefru256" };
rhash_info info_blake2s = { EXTENDED_HASH_ID(29), F_LE32, 32, "BLAKE2S", "blake2s" };
rhash_info info_blake2b = { EXTENDED_HASH_ID(30), F_LE64, 64, "BLAKE2B", "blake2b" };

/* some helper macros */
#define dgshft(name) ((uintptr_t)((char*)&((name##_ctx*)0)->hash))
Expand Down Expand Up @@ -162,6 +162,7 @@ void rhash_init_algorithms(unsigned mask)
(void)mask; /* unused now */

/* check RHASH_HASH_COUNT */
RHASH_ASSERT((RHASH_LOW_HASHES_MASK >> RHASH_HASH_COUNT) == 0);
RHASH_ASSERT(RHASH_COUNTOF(rhash_hash_info_default) == RHASH_HASH_COUNT);

#ifdef GENERATE_GOST94_LOOKUP_TABLE
Expand All @@ -176,12 +177,21 @@ void rhash_init_algorithms(unsigned mask)
* @param hash_id the id of hash algorithm
* @return pointer to the rhash_info structure containing the information
*/
const rhash_info* rhash_info_by_id(unsigned hash_id)
const rhash_hash_info* rhash_hash_info_by_id(unsigned hash_id)
{
hash_id &= RHASH_ALL_HASHES;
/* check that one and only one bit is set */
if (!hash_id || (hash_id & (hash_id - 1)) != 0) return NULL;
return rhash_info_table[rhash_ctz(hash_id)].info;
unsigned index;
if (IS_EXTENDED_HASH_ID(hash_id)) {
index = hash_id & ~RHASH_EXTENDED_BIT;
if (index >= RHASH_HASH_COUNT)
return NULL;
} else {
hash_id &= RHASH_LOW_HASHES_MASK;
/* check that one and only one bit is set */
if (!hash_id || (hash_id & (hash_id - 1)) != 0)
return NULL;
index = rhash_ctz(hash_id);
}
return &rhash_info_table[index];
}

/**
Expand All @@ -194,21 +204,21 @@ const rhash_info* rhash_info_by_id(unsigned hash_id)
* @param count pointer to store the number of returned ids to
* @return array of hash identifiers
*/
const unsigned* rhash_get_all_hash_ids(size_t* count)
const unsigned* rhash_get_all_hash_ids(unsigned all_id, size_t* count)
{
static const unsigned all_ids[] = {
RHASH_CRC32, RHASH_MD4, RHASH_MD5, RHASH_SHA1,
RHASH_TIGER, RHASH_TTH, RHASH_BTIH, RHASH_ED2K,
RHASH_AICH, RHASH_WHIRLPOOL, RHASH_RIPEMD160,
RHASH_GOST94, RHASH_GOST94_CRYPTOPRO, RHASH_HAS160,
RHASH_GOST12_256, RHASH_GOST12_512,
RHASH_SHA224, RHASH_SHA256, RHASH_SHA384, RHASH_SHA512,
RHASH_EDONR256, RHASH_EDONR512,
RHASH_SHA3_224, RHASH_SHA3_256, RHASH_SHA3_384, RHASH_SHA3_512,
RHASH_CRC32C, RHASH_SNEFRU128, RHASH_SNEFRU256,
RHASH_BLAKE2S, RHASH_BLAKE2B
EXTENDED_HASH_ID(0), EXTENDED_HASH_ID(1), EXTENDED_HASH_ID(2), EXTENDED_HASH_ID(3),
EXTENDED_HASH_ID(4), EXTENDED_HASH_ID(5), EXTENDED_HASH_ID(6), EXTENDED_HASH_ID(7),
EXTENDED_HASH_ID(8), EXTENDED_HASH_ID(9), EXTENDED_HASH_ID(10), EXTENDED_HASH_ID(11),
EXTENDED_HASH_ID(12), EXTENDED_HASH_ID(13), EXTENDED_HASH_ID(14), EXTENDED_HASH_ID(15),
EXTENDED_HASH_ID(16), EXTENDED_HASH_ID(17), EXTENDED_HASH_ID(18), EXTENDED_HASH_ID(19),
EXTENDED_HASH_ID(20), EXTENDED_HASH_ID(21), EXTENDED_HASH_ID(22), EXTENDED_HASH_ID(23),
EXTENDED_HASH_ID(24), EXTENDED_HASH_ID(25), EXTENDED_HASH_ID(26), EXTENDED_HASH_ID(27),
EXTENDED_HASH_ID(28), EXTENDED_HASH_ID(29), EXTENDED_HASH_ID(30)
};
*count = RHASH_HASH_COUNT;
static const unsigned count_low = rhash_popcount(RHASH_LOW_HASHES_MASK);
RHASH_ASSERT(RHASH_COUNTOF(all_ids) == RHASH_HASH_COUNT);
*count = (all_id == RHASH_ALL_HASHES ? RHASH_HASH_COUNT : count_low);
return all_ids;
}

Expand Down Expand Up @@ -309,6 +319,8 @@ static void rhash_crc32c_final(uint32_t* crc32c, unsigned char* result)
*/
size_t rhash_export_alg(unsigned hash_id, const void* ctx, void* out, size_t size)
{
if (IS_EXTENDED_HASH_ID(hash_id))
hash_id = 1 << GET_EXTENDED_HASH_ID_INDEX(hash_id);
switch (hash_id)
{
case RHASH_TTH:
Expand All @@ -332,6 +344,8 @@ size_t rhash_export_alg(unsigned hash_id, const void* ctx, void* out, size_t siz
*/
size_t rhash_import_alg(unsigned hash_id, void* ctx, const void* in, size_t size)
{
if (IS_EXTENDED_HASH_ID(hash_id))
hash_id = 1 << GET_EXTENDED_HASH_ID_INDEX(hash_id);
switch (hash_id)
{
case RHASH_TTH:
Expand Down
8 changes: 5 additions & 3 deletions librhash/algorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ extern rhash_info info_sha3_512;
extern rhash_info info_edr256;
extern rhash_info info_edr512;

#define IS_EXTENDED_RHASH_ID(hash_id) ((hash_id) & RHASH_EXTENDED_BIT)
#define IS_EXTENDED_HASH_ID(hash_id) ((hash_id) & RHASH_EXTENDED_BIT)
#define GET_EXTENDED_HASH_ID_INDEX(hash_id) ((unsigned)((hash_id) & ~RHASH_EXTENDED_BIT))
#define EXTENDED_HASH_ID(index) ((unsigned)(RHASH_EXTENDED_BIT | (index)))

/* rhash_info flags */
#define F_BS32 1 /* default output in base32 */
Expand All @@ -145,8 +147,8 @@ extern rhash_info info_edr512;
#endif

void rhash_init_algorithms(unsigned mask);
const rhash_info* rhash_info_by_id(unsigned hash_id); /* get hash sum info by hash id */
const unsigned* rhash_get_all_hash_ids(size_t* count);
const rhash_hash_info* rhash_hash_info_by_id(unsigned hash_id); /* get hash sum info by hash id */
const unsigned* rhash_get_all_hash_ids(unsigned all_id, size_t* count);

#if !defined(NO_IMPORT_EXPORT)
size_t rhash_export_alg(unsigned hash_id, const void* ctx, void* out, size_t size);
Expand Down
23 changes: 23 additions & 0 deletions librhash/byte_order.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,29 @@ unsigned rhash_ctz(unsigned x)
# endif /* _MSC_VER >= 1300... */
#endif /* rhash_ctz */

#ifndef rhash_ctz64
/**
* Returns index of the trailing bit of a 64-bit number.
* This is a plain C equivalent for GCC __builtin_ctzll() bit scan.
* Original author: Matt Taylor (2003).
*
* @param x the number to process
* @return zero-based index of the trailing bit
*/
unsigned rhash_ctz64(uint64_t x)
{
/* array for conversion to bit position */
static unsigned char bit_pos[64] = {
63, 30, 3, 32, 59, 14, 11, 33, 60, 24, 50, 9, 55, 19, 21, 34,
61, 29, 2, 53, 51, 23, 41, 18, 56, 28, 1, 43, 46, 27, 0, 35,
62, 31, 58, 4, 5, 49, 54, 6, 15, 52, 12, 40, 7, 42, 45, 16,
25, 57, 48, 13, 10, 39, 8, 44, 20, 47, 38, 22, 17, 37, 36, 26
};
uint32_t folded = (uint32_t)(((x - 1) >> 32) ^ (x - 1));
return bit_pos[folded * 0x78291ACF >> 26];
}
#endif /* rhash_ctz64 */

#ifndef rhash_popcount
/**
* Returns the number of 1-bits in x.
Expand Down
Loading

0 comments on commit 04caf13

Please sign in to comment.