Commit 1367fccc authored by Kitware Robot's avatar Kitware Robot Committed by Brad King

librhash 2016-11-01 (d839a1a8)

Code extracted from:

    https://github.com/rhash/rhash.git

at commit d839a1a853f22b8cfd26c2006ee5481739ea1114 (master).
parents
Pipeline #33812 passed with stage
* -whitespace
RHash License
Copyright (c) 2005-2014 Aleksey Kravchenko <rhash.admin@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
The Software is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Use this program at your own risk!
=== RHash program ===
RHash is a console utility for calculation and verification of magnet links
and a wide range of hash sums like CRC32, MD4, MD5, SHA1, SHA256, SHA512,
SHA3, AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94,
RIPEMD-160, HAS-160, EDON-R, Whirlpool and Snefru.
Hash sums are used to ensure and verify integrity of large volumes of data
for a long-term storing or transferring.
Features:
* Output in a predefined (SFV, BSD-like) or a user-defined format.
* Can calculate Magnet links.
* Updating hash files (adding hash sums of files missing in the hash file).
* Calculates several hash sums in one pass
* Ability to process directories recursively.
* Portability: the program works the same on Linux, *BSD or Windows.
=== The LibRHash library ===
LibRHash is a professional, portable, thread-safe C library for computing
a wide variety of hash sums, such as CRC32, MD4, MD5, SHA1, SHA256, SHA512,
SHA3, AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94,
RIPEMD-160, HAS-160, EDON-R, Whirlpool and Snefru.
Hash sums are used to ensure and verify integrity of large volumes of data
for a long-term storing or transferring.
Features:
* Small and easy to learn interface.
* Hi-level and Low-level API.
* Allows calculating of several hash functions simultaneously.
* Portability: the library works on Linux, *BSD and Windows.
=== Links ===
* Project Home Page: http://rhash.sourceforge.net/
* Official Releases: http://sf.net/projects/rhash/files/rhash/
* RHash hash functions descriptions http://rhash.anz.ru/hashes.php
* The table of the hash functions supported by RHash
http://sf.net/apps/mediawiki/rhash/index.php?title=Hash_sums
* ECRYPT: The Hash Function Zoo
http://ehash.iaik.tugraz.at/wiki/The_Hash_Function_Zoo
=== Getting latest source code ===
The latest source code can be obtained from Git repository by command:
git clone git://github.com/rhash/RHash.git
=== Notes on RHash License ===
The RHash program and LibRHash library are distributed under RHash License,
see the COPYING file for details. In particular, the program, the library
and source code can be used free of charge under the MIT, BSD, GPL,
commercial or freeware license without additional restrictions. In the case
the OSI-approved license is required the MIT license should be used.
/* algorithms.c - the algorithms supported by the rhash library
*
* Copyright: 2011-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
*/
#include <stdio.h>
#include <assert.h>
#include "byte_order.h"
#include "rhash.h"
#include "algorithms.h"
/* header files of all supported hash sums */
#include "aich.h"
#include "crc32.h"
#include "ed2k.h"
#include "edonr.h"
#include "gost.h"
#include "has160.h"
#include "md4.h"
#include "md5.h"
#include "ripemd-160.h"
#include "snefru.h"
#include "sha1.h"
#include "sha256.h"
#include "sha512.h"
#include "sha3.h"
#include "tiger.h"
#include "torrent.h"
#include "tth.h"
#include "whirlpool.h"
#ifdef USE_OPENSSL
/* note: BTIH and AICH depends on the used SHA1 algorithm */
# define NEED_OPENSSL_INIT (RHASH_MD4 | RHASH_MD5 | \
RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | RHASH_SHA512 | \
RHASH_BTIH | RHASH_AICH | RHASH_RIPEMD160 | RHASH_WHIRLPOOL)
#else
# define NEED_OPENSSL_INIT 0
#endif /* USE_OPENSSL */
#ifdef GENERATE_GOST_LOOKUP_TABLE
# define NEED_GOST_INIT (RHASH_GOST | RHASH_GOST_CRYPTOPRO)
#else
# define NEED_GOST_INIT 0
#endif /* GENERATE_GOST_LOOKUP_TABLE */
#ifdef GENERATE_CRC32_TABLE
# define NEED_CRC32_INIT RHASH_CRC32
#else
# define NEED_CRC32_INIT 0
#endif /* GENERATE_CRC32_TABLE */
#define RHASH_NEED_INIT_ALG (NEED_CRC32_INIT | NEED_GOST_INIT | NEED_OPENSSL_INIT)
unsigned rhash_uninitialized_algorithms = RHASH_NEED_INIT_ALG;
rhash_hash_info* rhash_info_table = rhash_hash_info_default;
int rhash_info_size = RHASH_HASH_COUNT;
static void rhash_crc32_init(uint32_t* crc32);
static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size);
static void rhash_crc32_final(uint32_t* crc32, unsigned char* result);
rhash_info info_crc32 = { RHASH_CRC32, F_BE32, 4, "CRC32", "crc32" };
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, 24, "TTH", "tree:tiger" };
rhash_info info_btih = { RHASH_BTIH, 0, 20, "BTIH", "btih" };
rhash_info info_ed2k = { RHASH_ED2K, F_LE32, 16, "ED2K", "ed2k" };
rhash_info info_aich = { RHASH_AICH, F_BS32, 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_gost = { RHASH_GOST, F_LE32, 32, "GOST", "gost" };
rhash_info info_gostpro = { RHASH_GOST_CRYPTOPRO, F_LE32, 32, "GOST-CRYPTOPRO", "gost-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_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" };
/* some helper macros */
#define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0)
#define dgshft2(name, field) (((char*)&((name##_ctx*)0)->field) - (char*)0)
#define ini(name) ((pinit_t)(name##_init))
#define upd(name) ((pupdate_t)(name##_update))
#define fin(name) ((pfinal_t)(name##_final))
#define iuf(name) ini(name), upd(name), fin(name)
#define diuf(name) dgshft(name), ini(name), upd(name), fin(name)
/* information about all hashes */
rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] =
{
{ &info_crc32, sizeof(uint32_t), 0, iuf(rhash_crc32), 0 }, /* 32 bit */
{ &info_md4, sizeof(md4_ctx), dgshft(md4), iuf(rhash_md4), 0 }, /* 128 bit */
{ &info_md5, sizeof(md5_ctx), dgshft(md5), iuf(rhash_md5), 0 }, /* 128 bit */
{ &info_sha1, sizeof(sha1_ctx), dgshft(sha1), iuf(rhash_sha1), 0 }, /* 160 bit */
{ &info_tiger, sizeof(tiger_ctx), dgshft(tiger), iuf(rhash_tiger), 0 }, /* 192 bit */
{ &info_tth, sizeof(tth_ctx), dgshft2(tth, tiger.hash), iuf(rhash_tth), 0 }, /* 192 bit */
{ &info_btih, sizeof(torrent_ctx), dgshft2(torrent, btih), iuf(bt), (pcleanup_t)bt_cleanup }, /* 160 bit */
{ &info_ed2k, sizeof(ed2k_ctx), dgshft2(ed2k, md4_context_inner.hash), iuf(rhash_ed2k), 0 }, /* 128 bit */
{ &info_aich, sizeof(aich_ctx), dgshft2(aich, sha1_context.hash), iuf(rhash_aich), (pcleanup_t)rhash_aich_cleanup }, /* 160 bit */
{ &info_whirlpool, sizeof(whirlpool_ctx), dgshft(whirlpool), iuf(rhash_whirlpool), 0 }, /* 512 bit */
{ &info_rmd160, sizeof(ripemd160_ctx), dgshft(ripemd160), iuf(rhash_ripemd160), 0 }, /* 160 bit */
{ &info_gost, sizeof(gost_ctx), dgshft(gost), iuf(rhash_gost), 0 }, /* 256 bit */
{ &info_gostpro, sizeof(gost_ctx), dgshft(gost), ini(rhash_gost_cryptopro), upd(rhash_gost), fin(rhash_gost), 0 }, /* 256 bit */
{ &info_has160, sizeof(has160_ctx), dgshft(has160), iuf(rhash_has160), 0 }, /* 160 bit */
{ &info_snf128, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru128), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 128 bit */
{ &info_snf256, sizeof(snefru_ctx), dgshft(snefru), ini(rhash_snefru256), upd(rhash_snefru), fin(rhash_snefru), 0 }, /* 256 bit */
{ &info_sha224, sizeof(sha256_ctx), dgshft(sha256), ini(rhash_sha224), upd(rhash_sha256), fin(rhash_sha256), 0 }, /* 224 bit */
{ &info_sha256, sizeof(sha256_ctx), dgshft(sha256), iuf(rhash_sha256), 0 }, /* 256 bit */
{ &info_sha384, sizeof(sha512_ctx), dgshft(sha512), ini(rhash_sha384), upd(rhash_sha512), fin(rhash_sha512), 0 }, /* 384 bit */
{ &info_sha512, sizeof(sha512_ctx), dgshft(sha512), iuf(rhash_sha512), 0 }, /* 512 bit */
{ &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */
{ &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */
{ &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_224), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 224 bit */
{ &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_256), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 256 bit */
{ &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_384), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 384 bit */
{ &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_512), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 512 bit */
};
/**
* Initialize requested algorithms.
*/
void rhash_init_algorithms(unsigned mask)
{
(void)mask; /* unused now */
/* verify that RHASH_HASH_COUNT is the index of the major bit of RHASH_ALL_HASHES */
assert(1 == (RHASH_ALL_HASHES >> (RHASH_HASH_COUNT - 1)));
#ifdef GENERATE_CRC32_TABLE
rhash_crc32_init_table();
#endif
#ifdef GENERATE_GOST_LOOKUP_TABLE
rhash_gost_init_table();
#endif
rhash_uninitialized_algorithms = 0;
}
/* CRC32 helper functions */
/**
* Initialize crc32 hash.
*
* @param crc32 pointer to the hash to initialize
*/
static void rhash_crc32_init(uint32_t* crc32)
{
*crc32 = 0; /* note: context size is sizeof(uint32_t) */
}
/**
* Calculate message CRC32 hash.
* Can be called repeatedly with chunks of the message to be hashed.
*
* @param crc32 pointer to the hash
* @param msg message chunk
* @param size length of the message chunk
*/
static void rhash_crc32_update(uint32_t* crc32, const unsigned char* msg, size_t size)
{
*crc32 = rhash_get_crc32(*crc32, msg, size);
}
/**
* Store calculated hash into the given array.
*
* @param crc32 pointer to the current hash value
* @param result calculated hash in binary form
*/
static void rhash_crc32_final(uint32_t* crc32, unsigned char* result)
{
#if defined(CPU_IA32) || defined(CPU_X64)
/* intel CPUs support assigment with non 32-bit aligned pointers */
*(unsigned*)result = be2me_32(*crc32);
#else
/* correct saving BigEndian integer on all archs */
result[0] = (unsigned char)(*crc32 >> 24), result[1] = (unsigned char)(*crc32 >> 16);
result[2] = (unsigned char)(*crc32 >> 8), result[3] = (unsigned char)(*crc32);
#endif
}
/* algorithms.h - rhash library algorithms */
#ifndef RHASH_ALGORITHMS_H
#define RHASH_ALGORITHMS_H
#include <stddef.h> /* for ptrdiff_t */
#include "rhash.h"
#include "byte_order.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef RHASH_API
/* modifier for RHash library functions */
# define RHASH_API
#endif
typedef void (*pinit_t)(void*);
typedef void (*pupdate_t)(void *ctx, const void* msg, size_t size);
typedef void (*pfinal_t)(void*, unsigned char*);
typedef void (*pcleanup_t)(void*);
/**
* Information about a hash function
*/
typedef struct rhash_hash_info
{
rhash_info *info;
size_t context_size;
ptrdiff_t digest_diff;
pinit_t init;
pupdate_t update;
pfinal_t final;
pcleanup_t cleanup;
} rhash_hash_info;
/**
* Information on a hash function and its context
*/
typedef struct rhash_vector_item
{
struct rhash_hash_info* hash_info;
void *context;
} rhash_vector_item;
/**
* The rhash context containing contexts for several hash functions
*/
typedef struct rhash_context_ext
{
struct rhash_context rc;
unsigned hash_vector_size; /* number of contained hash sums */
unsigned flags;
unsigned state;
void *callback, *callback_data;
void *bt_ctx;
rhash_vector_item vector[1]; /* contexts of contained hash sums */
} rhash_context_ext;
extern rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT];
extern rhash_hash_info* rhash_info_table;
extern int rhash_info_size;
extern unsigned rhash_uninitialized_algorithms;
extern rhash_info info_crc32;
extern rhash_info info_md4;
extern rhash_info info_md5;
extern rhash_info info_sha1;
extern rhash_info info_tiger;
extern rhash_info info_tth ;
extern rhash_info info_btih;
extern rhash_info info_ed2k;
extern rhash_info info_aich;
extern rhash_info info_whirlpool;
extern rhash_info info_rmd160;
extern rhash_info info_gost;
extern rhash_info info_gostpro;
extern rhash_info info_has160;
extern rhash_info info_snf128;
extern rhash_info info_snf256;
extern rhash_info info_sha224;
extern rhash_info info_sha256;
extern rhash_info info_sha384;
extern rhash_info info_sha512;
extern rhash_info info_sha3_224;
extern rhash_info info_sha3_256;
extern rhash_info info_sha3_384;
extern rhash_info info_sha3_512;
extern rhash_info info_edr256;
extern rhash_info info_edr512;
/* rhash_info flags */
#define F_BS32 1 /* default output in base32 */
#define F_SWAP32 2 /* Big endian flag */
#define F_SWAP64 4
/* define endianness flags */
#ifndef CPU_BIG_ENDIAN
#define F_LE32 0
#define F_LE64 0
#define F_BE32 F_SWAP32
#define F_BE64 F_SWAP64
#else
#define F_LE32 F_SWAP32
#define F_LE64 F_SWAP64
#define F_BE32 0
#define F_BE64 0
#endif
void rhash_init_algorithms(unsigned mask);
#if defined(OPENSSL_RUNTIME) && !defined(USE_OPENSSL)
# define USE_OPENSSL
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* RHASH_ALGORITHMS_H */
/* byte_order.c - byte order related platform dependent routines,
*
* Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
*/
#include "byte_order.h"
#if !(__GNUC__ >= 4 || (__GNUC__ ==3 && __GNUC_MINOR__ >= 4)) /* if !GCC or GCC < 4.3 */
# if _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) /* if MSVC++ >= 2002 on x86/x64 */
# include <intrin.h>
# pragma intrinsic(_BitScanForward)
/**
* Returns index of the trailing bit of x.
*
* @param x the number to process
* @return zero-based index of the trailing bit
*/
unsigned rhash_ctz(unsigned x)
{
unsigned long index;
unsigned char isNonzero = _BitScanForward(&index, x); /* MSVC intrinsic */
return (isNonzero ? (unsigned)index : 0);
}
# else /* _MSC_VER >= 1300... */
/**
* Returns index of the trailing bit of a 32-bit number.
* This is a plain C equivalent for GCC __builtin_ctz() bit scan.
*
* @param x the number to process
* @return zero-based index of the trailing bit
*/
unsigned rhash_ctz(unsigned x)
{
/* array for conversion to bit position */
static unsigned char 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
};
/* The De Bruijn bit-scan was devised in 1997, according to Donald Knuth
* by Martin Lauter. The constant 0x077CB531UL is a De Bruijn sequence,
* which produces a unique pattern of bits into the high 5 bits for each
* possible bit position that it is multiplied against.
* See http://graphics.stanford.edu/~seander/bithacks.html
* and http://chessprogramming.wikispaces.com/BitScan */
return (unsigned)bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];
}
# endif /* _MSC_VER >= 1300... */
#endif /* !(GCC >= 4.3) */
/**
* Copy a memory block with simultaneous exchanging byte order.
* The byte order is changed from little-endian 32-bit integers
* to big-endian (or vice-versa).
*
* @param to the pointer where to copy memory block
* @param index the index to start writing from
* @param from the source block to copy
* @param length length of the memory block
*/
void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length)
{
/* if all pointers and length are 32-bits aligned */
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 3) ) {
/* copy memory as 32-bit words */
const uint32_t* src = (const uint32_t*)from;
const uint32_t* end = (const uint32_t*)((const char*)src + length);
uint32_t* dst = (uint32_t*)((char*)to + index);
while (src < end) *(dst++) = bswap_32( *(src++) );
} else {
const char* src = (const char*)from;
for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 3] = *(src++);
}
}
/**
* Copy a memory block with changed byte order.
* The byte order is changed from little-endian 64-bit integers
* to big-endian (or vice-versa).
*
* @param to the pointer where to copy memory block
* @param index the index to start writing from
* @param from the source block to copy
* @param length length of the memory block
*/
void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length)
{
/* if all pointers and length are 64-bits aligned */
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 7) ) {
/* copy aligned memory block as 64-bit integers */
const uint64_t* src = (const uint64_t*)from;
const uint64_t* end = (const uint64_t*)((const char*)src + length);
uint64_t* dst = (uint64_t*)((char*)to + index);
while (src < end) *(dst++) = bswap_64( *(src++) );
} else {
const char* src = (const char*)from;
for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 7] = *(src++);
}
}
/**
* Copy data from a sequence of 64-bit words to a binary string of given length,
* while changing byte order.
*
* @param to the binary string to receive data
* @param from the source sequence of 64-bit words
* @param length the size in bytes of the data being copied
*/
void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length)
{
/* if all pointers and length are 64-bits aligned */
if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | length ) & 7) ) {
/* copy aligned memory block as 64-bit integers */
const uint64_t* src = (const uint64_t*)from;
const uint64_t* end = (const uint64_t*)((const char*)src + length);
uint64_t* dst = (uint64_t*)to;
while (src < end) *(dst++) = bswap_64( *(src++) );
} else {
size_t index;
char* dst = (char*)to;
for (index = 0; index < length; index++) *(dst++) = ((char*)from)[index ^ 7];
}
}
/**
* Exchange byte order in the given array of 32-bit integers.
*
* @param arr the array to process
* @param length array length
*/
void rhash_u32_mem_swap(unsigned *arr, int length)
{
unsigned* end = arr + length;
for (; arr < end; arr++) {
*arr = bswap_32(*arr);
}
}
/* byte_order.h */
#ifndef BYTE_ORDER_H
#define BYTE_ORDER_H
#include "ustd.h"
#include <stdlib.h>
#ifdef IN_RHASH
#include "config.h"
#endif
#ifdef __GLIBC__
# include <endian.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* if x86 compatible cpu */
#if defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(__pentium__) || \
defined(__pentiumpro__) || defined(__pentium4__) || \
defined(__nocona__) || defined(prescott) || defined(__core2__) || \
defined(__k6__) || defined(__k8__) || defined(__athlon__) || \
defined(__amd64) || defined(__amd64__) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \
defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)
/* detect if x86-64 instruction set is supported */
# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
# define CPU_X64
# else
# define CPU_IA32
# endif
#endif
/* detect CPU endianness */
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
defined(CPU_IA32) || defined(CPU_X64) || \
defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \
defined(vax) || defined(MIPSEL) || defined(_ARM_) || defined(__arm__)
# define CPU_LITTLE_ENDIAN
# define IS_BIG_ENDIAN 0
# define IS_LITTLE_ENDIAN 1
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
defined(__sparc) || defined(__sparc__) || defined(sparc) || \
defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \
defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \
defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \
defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \
defined(__s390__) || defined(__s390x__) || defined(sel)
# define CPU_BIG_ENDIAN
# define IS_BIG_ENDIAN 1
# define IS_LITTLE_ENDIAN 0
#else
# error "Can't detect CPU architechture"
#endif
#define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0)))
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
#if defined(_MSC_VER)
#define ALIGN_ATTR(n) __declspec(align(n))
#elif defined(__GNUC__)
#define ALIGN_ATTR(n) __attribute__((aligned (n)))
#else
#define ALIGN_ATTR(n) /* nothing */
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define I64(x) x##ui64
#else
#define I64(x) x##LL
#endif
/* convert a hash flag to index */
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) /* GCC < 3.4 */
# define rhash_ctz(x) __builtin_ctz(x)
#else
unsigned rhash_ctz(unsigned); /* define as function */
#endif
void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length);
void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length);
void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length);
void rhash_u32_mem_swap(unsigned *p, int length_in_u32);
/* define bswap_32 */
#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__)
/* for intel x86 CPU */
static inline uint32_t bswap_32(uint32_t x) {
__asm("bswap\t%0" : "=r" (x) : "0" (x));
return x;
}
#elif defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
/* for GCC >= 4.3 */
# define bswap_32(x) __builtin_bswap32(x)
#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
# define bswap_32(x) _byteswap_ulong((unsigned long)x)
#elif !defined(__STRICT_ANSI__)
/* general bswap_32 definition */
static inline uint32_t bswap_32(uint32_t x) {
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
return (x >> 16) | (x << 16);
}
#else
#define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#endif /* bswap_32 */
#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
# define bswap_64(x) __builtin_bswap64(x)
#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
# define bswap_64(x) _byteswap_uint64((__int64)x)
#elif !defined(__STRICT_ANSI__)
static inline uint64_t bswap_64(uint64_t x) {
union {
uint64_t ll;
uint32_t l[2];
} w, r;
w.ll = x;
r.l[0] = bswap_32(w.l[1]);
r.l[1] = bswap_32(w.l[0]);
return r.ll;
}
#else
#error "bswap_64 unsupported"
#endif
#ifdef CPU_BIG_ENDIAN
# define be2me_32(x) (x)
# define be2me_64(x) (x)
# define le2me_32(x) bswap_32(x)
# define le2me_64(x) bswap_64(x)
# define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
# define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
# define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
# define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
# define me64_to_be_str(to, from, length) memcpy((to), (from), (length))
# define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
#else /* CPU_BIG_ENDIAN */
# define be2me_32(x) bswap_32(x)
# define be2me_64(x) bswap_64(x)
# define le2me_32(x) (x)
# define le2me_64(x) (x)
# define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
# define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
# define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
# define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
# define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
#endif /* CPU_BIG_ENDIAN */
/* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */
#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))