diff --git a/hphp/runtime/ext/ext_hash.cpp b/hphp/runtime/ext/ext_hash.cpp index 30182e7e9..5cc81ae55 100644 --- a/hphp/runtime/ext/ext_hash.cpp +++ b/hphp/runtime/ext/ext_hash.cpp @@ -27,7 +27,7 @@ #include #include #include - +#include #include #include @@ -86,6 +86,10 @@ public: HashEngines["haval192,5"] = HashEnginePtr(new hash_haval(5,192)); HashEngines["haval224,5"] = HashEnginePtr(new hash_haval(5,224)); HashEngines["haval256,5"] = HashEnginePtr(new hash_haval(5,256)); + HashEngines["fnv132"] = HashEnginePtr(new hash_fnv132(false)); + HashEngines["fnv1a32"] = HashEnginePtr(new hash_fnv132(true)); + HashEngines["fnv164"] = HashEnginePtr(new hash_fnv164(false)); + HashEngines["fnv1a64"] = HashEnginePtr(new hash_fnv164(true)); } }; diff --git a/hphp/runtime/ext/hash/hash_fnv1.cpp b/hphp/runtime/ext/hash/hash_fnv1.cpp new file mode 100644 index 000000000..664d14c0b --- /dev/null +++ b/hphp/runtime/ext/hash/hash_fnv1.cpp @@ -0,0 +1,137 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) | + | Copyright (c) 1997-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#include + +#define PHP_FNV1_32_INIT ((uint32_t)0x811c9dc5) +#define PHP_FNV_32_PRIME ((uint32_t)0x01000193) + +#define PHP_FNV1_64_INIT ((uint64_t)0xcbf29ce484222325ULL) +#define PHP_FNV_64_PRIME ((uint64_t)0x100000001b3ULL) + + +namespace HPHP { +/////////////////////////////////////////////////////////////////////////////// + +typedef struct { + uint32_t state; +} PHP_FNV132_CTX; + +typedef struct { + uint64_t state; +} PHP_FNV164_CTX; + +hash_fnv132::hash_fnv132(bool a) + : HashEngine(4, 4, sizeof(PHP_FNV132_CTX)), m_a(a) { +} + +hash_fnv164::hash_fnv164(bool a) + : HashEngine(8, 4, sizeof(PHP_FNV164_CTX)), m_a(a) { +} + +void hash_fnv132::hash_init(void *context_) { + PHP_FNV132_CTX *context = (PHP_FNV132_CTX*)context_; + context->state = PHP_FNV1_32_INIT; +} + +void hash_fnv164::hash_init(void *context_) { + PHP_FNV164_CTX *context = (PHP_FNV164_CTX*)context_; + context->state = PHP_FNV1_64_INIT; +} + +void hash_fnv132::hash_update(void *context_, const unsigned char *input, + unsigned int len) { + PHP_FNV132_CTX *context = (PHP_FNV132_CTX*)context_; + const unsigned char *bp = (unsigned char *)input; /* start of buffer */ + const unsigned char *be = bp + len; /* beyond end of buffer */ + + /* + * FNV-1 hash each octet in the buffer + */ + while (bp < be) { + if (m_a == false) { + /* multiply by the 32 bit FNV magic prime mod 2^32 */ + context->state *= PHP_FNV_32_PRIME; + + /* xor the bottom with the current octet */ + context->state ^= (uint32_t)*bp++; + } else { + /* xor the bottom with the current octet */ + context->state ^= (uint32_t)*bp++; + + /* multiply by the 32 bit FNV magic prime mod 2^32 */ + context->state *= PHP_FNV_32_PRIME; + } + } +} + +void hash_fnv164::hash_update(void *context_, const unsigned char *input, + unsigned int len) { + PHP_FNV164_CTX *context = (PHP_FNV164_CTX*)context_; + unsigned char *bp = (unsigned char *)input; /* start of buffer */ + unsigned char *be = bp + len; /* beyond end of buffer */ + + /* + * FNV-1 hash each octet of the buffer + */ + while (bp < be) { + if (m_a == false) { + /* multiply by the 64 bit FNV magic prime mod 2^64 */ + context->state *= PHP_FNV_64_PRIME; + + /* xor the bottom with the current octet */ + context->state ^= (uint64_t)*bp++; + } else { + /* xor the bottom with the current octet */ + context->state ^= (uint64_t)*bp++; + + /* multiply by the 64 bit FNV magic prime mod 2^64 */ + context->state *= PHP_FNV_64_PRIME; + } + } +} + +void hash_fnv132::hash_final(unsigned char *digest, void *context_) { + PHP_FNV132_CTX *context = (PHP_FNV132_CTX*)context_; +#ifdef WORDS_BIGENDIAN + memcpy(digest, &context->state, 4); +#else + int i = 0; + unsigned char *c = (unsigned char *) &context->state; + + for (i = 0; i < 4; i++) { + digest[i] = c[3 - i]; + } +#endif +} + +void hash_fnv164::hash_final(unsigned char *digest, void *context_) { + PHP_FNV164_CTX *context = (PHP_FNV164_CTX*)context_; +#ifdef WORDS_BIGENDIAN + memcpy(digest, &context->state, 8); +#else + int i = 0; + unsigned char *c = (unsigned char *) &context->state; + + for (i = 0; i < 8; i++) { + digest[i] = c[7 - i]; + } +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +} diff --git a/hphp/runtime/ext/hash/hash_fnv1.h b/hphp/runtime/ext/hash/hash_fnv1.h new file mode 100644 index 000000000..37dfb858f --- /dev/null +++ b/hphp/runtime/ext/hash/hash_fnv1.h @@ -0,0 +1,55 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) | + | Copyright (c) 1997-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#ifndef incl_HPHP_EXT_HASH_FNV1_H_ +#define incl_HPHP_EXT_HASH_FNV1_H_ + +#include + +namespace HPHP { +/////////////////////////////////////////////////////////////////////////////// + +class hash_fnv132 : public HashEngine { +public: + explicit hash_fnv132(bool a); + + virtual void hash_init(void *context); + virtual void hash_update(void *context, const unsigned char *buf, + unsigned int count); + virtual void hash_final(unsigned char *digest, void *context); + +private: + bool m_a; +}; + +class hash_fnv164 : public HashEngine { +public: + explicit hash_fnv164(bool a); + + virtual void hash_init(void *context); + virtual void hash_update(void *context, const unsigned char *buf, + unsigned int count); + virtual void hash_final(unsigned char *digest, void *context); + +private: + bool m_a; +}; + +/////////////////////////////////////////////////////////////////////////////// +} + +#endif // incl_HPHP_EXT_HASH_FNV1_H_ diff --git a/hphp/test/zend/bad/ext-hash/fnv132.php b/hphp/test/zend/good/ext-hash/fnv132.php similarity index 100% rename from hphp/test/zend/bad/ext-hash/fnv132.php rename to hphp/test/zend/good/ext-hash/fnv132.php diff --git a/hphp/test/zend/bad/ext-hash/fnv132.php.expectf b/hphp/test/zend/good/ext-hash/fnv132.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-hash/fnv132.php.expectf rename to hphp/test/zend/good/ext-hash/fnv132.php.expectf diff --git a/hphp/test/zend/bad/ext-hash/fnv164.php b/hphp/test/zend/good/ext-hash/fnv164.php similarity index 100% rename from hphp/test/zend/bad/ext-hash/fnv164.php rename to hphp/test/zend/good/ext-hash/fnv164.php diff --git a/hphp/test/zend/bad/ext-hash/fnv164.php.expectf b/hphp/test/zend/good/ext-hash/fnv164.php.expectf similarity index 100% rename from hphp/test/zend/bad/ext-hash/fnv164.php.expectf rename to hphp/test/zend/good/ext-hash/fnv164.php.expectf