/
hash.ts
94 lines (84 loc) · 2.71 KB
/
hash.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//================================================================
/**
* @packageDocumentation
* @module std
*/
//================================================================
import { IComparable } from "./IComparable";
import { get_uid } from "./uid";
/**
* Hash function.
*
* @param items The items to be hashed.
* @return The hash code.
*/
export function hash(...items: any[]): number
{
let ret: number = INIT_VALUE;
for (let item of items)
{
item = item ? item.valueOf() : item;
let type: string = typeof item;
if (type === "boolean") // BOOLEAN -> 1 BYTE
ret = _Hash_boolean(item, ret);
else if (type === "number" || type === "bigint") // NUMBER -> 8 BYTES
ret = _Hash_number(item, ret);
else if (type === "string") // STRING -> {LENGTH} BYTES
ret = _Hash_string(item, ret);
else if (item instanceof Object && (<any>item as IComparable<{}>).hashCode instanceof Function)
{
let hashed: number = (<any>item as IComparable<{}>).hashCode();
if (items.length === 1)
return hashed;
else
{
ret = ret ^ hashed;
ret *= MULTIPLIER;
}
}
else // object | null | undefined
ret = _Hash_number(get_uid(item), ret);
}
return Math.abs(ret);
}
function _Hash_boolean(val: boolean, ret: number): number
{
ret ^= val ? 1 : 0;
ret *= MULTIPLIER;
return ret;
}
function _Hash_number(val: number, ret: number): number
{
return _Hash_string(val.toString(), ret);
// // ------------------------------------------
// // IN C++
// // CONSIDER A NUMBER AS A STRING
// // HASH<STRING>((CHAR*)&VAL, 8)
// // ------------------------------------------
// // CONSTRUCT BUFFER AND BYTE_ARRAY
// let buffer: ArrayBuffer = new ArrayBuffer(8);
// let byteArray: Int8Array = new Int8Array(buffer);
// let valueArray: Float64Array = new Float64Array(buffer);
// valueArray[0] = val;
// for (let i: number = 0; i < byteArray.length; ++i)
// {
// let byte = (byteArray[i] < 0) ? byteArray[i] + 256 : byteArray[i];
// ret ^= byte;
// ret *= _HASH_MULTIPLIER;
// }
// return Math.abs(ret);
}
function _Hash_string(str: string, ret: number): number
{
for (let i: number = 0; i < str.length; ++i)
{
ret ^= str.charCodeAt(i);
ret *= MULTIPLIER;
}
return Math.abs(ret);
}
/* ---------------------------------------------------------
RESERVED ITEMS
--------------------------------------------------------- */
const INIT_VALUE: number = 2166136261;
const MULTIPLIER: number = 16777619;