Javascript 将哈希字符串从C转换为JS
我试图从Mozilla Firefox代码库转换此函数,它名为Javascript 将哈希字符串从C转换为JS,javascript,c++,c,firefox-addon,Javascript,C++,C,Firefox Addon,我试图从Mozilla Firefox代码库转换此函数,它名为HashString。它调用了一组函数,这些函数都在这个文件中: 下面是它调用的C函数: static const uint32_t kGoldenRatioU32 = 0x9E3779B9U; MOZ_WARN_UNUSED_RESULT inline uint32_t HashString(const wchar_t* aStr) { return detail::HashUntilZero(aStr); } templa
HashString
。它调用了一组函数,这些函数都在这个文件中:
下面是它调用的C函数:
static const uint32_t kGoldenRatioU32 = 0x9E3779B9U;
MOZ_WARN_UNUSED_RESULT inline uint32_t
HashString(const wchar_t* aStr)
{
return detail::HashUntilZero(aStr);
}
template<typename T>
uint32_t
HashUntilZero(const T* aStr)
{
uint32_t hash = 0;
for (T c; (c = *aStr); aStr++) {
hash = AddToHash(hash, c);
}
return hash;
}
MOZ_WARN_UNUSED_RESULT inline uint32_t
AddToHash(uint32_t aHash, A* aA)
{
/*
* You might think this function should just take a void*. But then we'd only
* catch data pointers and couldn't handle function pointers.
*/
static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!");
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA));
}
inline uint32_t
AddUintptrToHash<8>(uint32_t aHash, uintptr_t aValue)
{
/*
* The static cast to uint64_t below is necessary because this function
* sometimes gets compiled on 32-bit platforms (yes, even though it's a
* template and we never call this particular override in a 32-bit build). If
* we do aValue >> 32 on a 32-bit machine, we're shifting a 32-bit uintptr_t
* right 32 bits, and the compiler throws an error.
*/
uint32_t v1 = static_cast<uint32_t>(aValue);
uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32);
return AddU32ToHash(AddU32ToHash(aHash, v1), v2);
}
inline uint32_t
AddU32ToHash(uint32_t aHash, uint32_t aValue)
{
return kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue);
}
inline uint32_t
RotateBitsLeft32(uint32_t aValue, uint8_t aBits)
{
MOZ_ASSERT(aBits < 32);
return (aValue << aBits) | (aValue >> (32 - aBits));
}
静态常数uint32\u t kGoldenRatioU32=0x9E3779B9U;
MOZ_WARN_UNUSED_结果内嵌uint32_t
哈希字符串(常量wchar\u t*aStr)
{
返回详细信息::HashUntilZero(aStr);
}
模板
uint32\u t
HashUntilZero(常数T*aStr)
{
uint32\u t hash=0;
for(tc;(c=*aStr);aStr++){
hash=AddToHash(hash,c);
}
返回散列;
}
MOZ_WARN_UNUSED_结果内嵌uint32_t
AddToHash(uint32_t aHash,A*aA)
{
/*
*你可能会认为这个函数应该是一个空的*,但是我们只需要
*捕获数据指针,但无法处理函数指针。
*/
静态断言(sizeof(aA)=sizeof(uintpttr\u t),“奇怪的指针!”);
返回细节::AddUintptrToHash(aHash,uintpttr_t(aA));
}
内联uint32\u t
AddUintptrToHash(uint32\u t aHash,uintpttr\u t aValue)
{
/*
*以下uint64的静态强制转换是必要的,因为此功能
*有时在32位平台上编译(是的,尽管它是一个
*我们在32位构建中从不调用此特定重写)。如果
*我们在32位机器上执行aValue>>32,我们正在移动32位uintptr\t
*右转32位,编译器将抛出一个错误。
*/
uint32_t v1=静态播放(aValue);
uint32\u t v2=静态播放(静态播放(aValue)>>32);
返回AddU32ToHash(AddU32ToHash(aHash,v1),v2);
}
内联uint32\u t
addu32-tohash(uint32-aHash,uint32-aValue)
{
返回kGoldenRatioU32*(RotateBitsLeft32(aHash,5)^aValue);
}
内联uint32\u t
RotateBitsLeft32(uint32可用,uint8可用)
{
MOZ_断言(aBits<32);
返回(aValue>(32-aBits));
}
这是我的js代码:
function HashString(aStr, aLength) {
// moz win32 hash function
if (aLength) {
console.error('NS_ERROR_NOT_IMPLEMENTED');
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
} else {
return HashUntilZero(aStr);
}
}
function HashUntilZero(aStr) {
var hash = 0;
//for (T c; (c = *aStr); aStr++) {
for (var c=0; c<aStr.length; c++) {
hash = AddToHash(hash, aStr.charCodeAt(c));
}
return hash;
}
function AddToHash(aHash, aA) {
//return detail::AddU32ToHash(aHash, aA);
//return AddU32ToHash(aHash, aA);
//return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
return AddUintptrToHash(aHash, aA);
}
function AddUintptrToHash(aHash, aValue) {
//return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
return AddU32ToHash(aHash, aValue);
}
function AddU32ToHash(aHash, aValue) {
var kGoldenRatioU32 = 0x9E3779B9;
return (kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue));
}
function RotateBitsLeft32(aValue, aBits) {
// MOZ_ASSERT(aBits < 32);
return (aValue << aBits) | (aValue >> (32 - aBits));
}
console.log(HashString('C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10')); // should return 3181739213
函数哈希字符串(aStr,aLength){
//moz win32哈希函数
if(aLength){
console.error('NS_error_NOT_IMPLEMENTED');
抛出组件.results.NS\u错误\u未实现;
}否则{
返回HashUntilZero(aStr);
}
}
函数HashUntilZero(aStr){
var散列=0;
//for(tc;(c=*aStr);aStr++){
对于(VarC=0;c(32-aBits));
}
log(HashString('C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10');//应返回3181739213
执行HashString('C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10')时,这不正常<代码>应该返回给我<代码> 3181739213代码>但是它不是。它继续返回给我:<代码> -159266146140 < /Cord>< P> >让我们先实现一个更为简单的C++版本,它还可以卸载我们稍后比较的中间值。
#include <iostream>
#include <iomanip>
#include <stdint.h>
using namespace std;
static const uint32_t gr = 0x9E3779B9U;
template<typename T>
static uint32_t add(uint32_t hash, T val) {
const uint32_t rv = gr * (((hash << 5) | (hash >> 27)) ^ val);
cerr << dec << setw(7) << (uint32_t)val << " " << setw(14) << rv << " " << hex << rv << endl;
return rv;
}
int main() {
const auto text = string("C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10");
uint32_t rv = 0;
for (auto c: text) {
rv = add(rv, c);
}
cout << "Result: " << dec << setw(14) << rv << " " << hex << rv << endl;
}
可能不是最有效的实现,但至少它可以工作;)有一种更简单的方法
var file = new FileUtils.File('C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10');
file.QueryInterface(Ci.nsIHashable);
console.log(file.hashCode === 3181739213);
在您位于
HashUntillZero
的for循环中,您正在递增字符串而不是计数器,这会弄乱其余的代码。啊,非常感谢@entorarox!我错过了它,我已经修复了它,但现在它在我应该得到3181739213
时给了我-159266146140
:(您也没有复制黄金比例的最后一个十六进制,但这是一个相当容易的错误,我自己第一次就错过了。编辑:C++/C可能处理右移的方式与javascript不同,但我可以确定。C:static const uint32\u t kGoldenRatioU32=0x9E3779B9U;
,JS:var kGoldenRatioU32=0x9e379b9;
我已经检查了类型声明,我相信问题就在那里,javascript没有无符号的32位整数,只有有符号的,您必须将有符号的32位整数转换为普通的javascriptnumber
(因为这不受32位的限制)在AddU32ToHash
Right中使用它之前…nsIFile
是nsifhash
,很好的捕获。所以对于nsIFile
兼容的路径,这个路径可以很好地工作,而且确实更简单。嘿,paa和@nmaier,当我复制粘贴这个代码时,它会给我3375393251
它应该是3181739213
,我确信关于这一点,因为这是我的个人资料的browser.taskbar.lastgroupid
值。这真的很奇怪。你知道怎么回事吗?hashCode是3181739213。可能lastgroupid不包含hashCode的值。@Noitidart,nmaier的实现和nsIHashable都返回相同的结果,至少示例中是这样。和即使它们是不同的,我也怀疑故障是在NsihhAsple的边上的。您所指的代码显示了路径的散列串是有条件使用的。您的代码是否考虑了这些条件?在我的系统中,它返回了3181739213。另一方面,在我的系统上,这个路径不存在。您可以检查代码是否为<代码>:\\用户\\未知\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10是3103912233吗?
var file = new FileUtils.File('C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10');
file.QueryInterface(Ci.nsIHashable);
console.log(file.hashCode === 3181739213);