mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-23 22:01:20 -08:00
build(site): [SITE-07] verify modified forks and preserve upstream author notices
This commit is contained in:
1 parent
d2a83f8a69
commit
3136eb2402
31 files changed
+2567
-23
No files matched your search
@@ -0,0 +1,163 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "SITE-07",
|
||||
"archives": [
|
||||
{
|
||||
"id": "replicator-1.0.1",
|
||||
"name": "replicator",
|
||||
"version": "1.0.1",
|
||||
"tarball": "https://registry.npmjs.org/replicator/-/replicator-1.0.1.tgz",
|
||||
"integrity": "sha512-BwkUVdSQ08mGLa1OoP8thQ0zTUcxplGNZ1p0rsaSEL7xc4N3v5kkR/WFLjikkdjQPjp+67p24QOerWwIj2oN4g==",
|
||||
"sha256": "2baede665f8f4899b7196251e39c775ee0111872f04afef08ab5e2e6ada70925",
|
||||
"notices": [
|
||||
{
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/replicator-1.0.1-LICENSE.txt",
|
||||
"member": "package/LICENSE",
|
||||
"sha256": "52f634086a97b3861a35afff7acf703ddbd5add8e617f6a1f540ae2f2c621284"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "stylis-3.5.4",
|
||||
"name": "stylis",
|
||||
"version": "3.5.4",
|
||||
"tarball": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz",
|
||||
"integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==",
|
||||
"sha256": "8e378e277ef50bd5282045dfac95019e66986d7d3819205a9e99c93220e3e950",
|
||||
"notices": [
|
||||
{
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/stylis-3.5.4-LICENSE.txt",
|
||||
"member": "package/LICENSE.md",
|
||||
"sha256": "045109dfd0547aa898408d08593e1adc41e9705519ba8a20baff89e7c6c52e91"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"compiler": {
|
||||
"archive": {
|
||||
"id": "typescript-4.1.2",
|
||||
"name": "typescript",
|
||||
"version": "4.1.2",
|
||||
"tarball": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
|
||||
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
|
||||
"sha256": "383b18630fc00016cb7bde65f111e79d43fccb8c025faf33d7a3a07a5abdf026"
|
||||
},
|
||||
"member": "package/lib/typescript.js",
|
||||
"sha256": "7fb17b02f99364980c5f8540175309b09932f8fad41dcc7e9429d335535604e0",
|
||||
"version": "4.1.2",
|
||||
"options": {
|
||||
"target": 0,
|
||||
"module": 1,
|
||||
"newLine": 1
|
||||
}
|
||||
},
|
||||
"remotes": [
|
||||
{
|
||||
"id": "replicator-source",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/replicator-source.txt",
|
||||
"sha256": "2bf53776cfd80aaf6365d4419ab910ca282db649fc942ac285765748db6f875e",
|
||||
"gitBlobSha": "7399074f5c003120d17d9bb48e6b0832434d64dc",
|
||||
"apiUrl": "https://api.github.com/repos/samdenty/console-feed/contents/src/Transform/replicator/index.ts?ref=de41ef2662019c645a652199d9bdbbfc71419f5e",
|
||||
"url": "https://github.com/samdenty/console-feed/blob/de41ef2662019c645a652199d9bdbbfc71419f5e/src/Transform/replicator/index.ts"
|
||||
},
|
||||
{
|
||||
"id": "emotion-build",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/emotion-build.txt",
|
||||
"sha256": "7d9a3d176b6da384d729d45f7e36dec6cd6effb85cd19d486f4f50af5cf2925f",
|
||||
"gitBlobSha": "fdd877e14000329ff556ca2f1aa7fc44c724060d",
|
||||
"apiUrl": "https://api.github.com/repos/emotion-js/emotion/git/blobs/fdd877e14000329ff556ca2f1aa7fc44c724060d",
|
||||
"url": "https://github.com/emotion-js/emotion/blob/6dd425bd1b8db7ab5144cca81b592639a68af2cb/packages/stylis/build.js"
|
||||
},
|
||||
{
|
||||
"id": "emotion-stylis-source",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/emotion-stylis-source.txt",
|
||||
"sha256": "2d49f50cb973b395bb30ca1d03955599e6220dd347d57ae38324afe8c734506a",
|
||||
"gitBlobSha": "c6b56ec79517a0dce4b84eceb15acb4730e04101",
|
||||
"apiUrl": "https://api.github.com/repos/emotion-js/emotion/git/blobs/c6b56ec79517a0dce4b84eceb15acb4730e04101",
|
||||
"url": "https://github.com/emotion-js/emotion/blob/6dd425bd1b8db7ab5144cca81b592639a68af2cb/packages/stylis/src/stylis.min.js"
|
||||
},
|
||||
{
|
||||
"id": "gary-readme",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/gary-readme.txt",
|
||||
"sha256": "73b67c593a2a0d6395bfe90d3bad32556ed5e7ce71883062efebc643d4e4b7b4",
|
||||
"gitBlobSha": "567ae1bca393a150e129cec8d60230a7b88e77c7",
|
||||
"apiUrl": "https://api.github.com/repos/garycourt/murmurhash-js/contents/README.md?ref=23dc2e7008582ca3ef69d8623f02bba4c8dd05e5",
|
||||
"url": "https://github.com/garycourt/murmurhash-js/blob/23dc2e7008582ca3ef69d8623f02bba4c8dd05e5/README.md"
|
||||
},
|
||||
{
|
||||
"id": "smhasher",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/smhasher.txt",
|
||||
"sha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
|
||||
"gitBlobSha": "cd1e53a9b92620d2656eae423017f81be1fb3ad1",
|
||||
"apiUrl": "https://api.github.com/repos/aappleby/smhasher/contents/src/MurmurHash2.cpp?ref=61a0530f28277f2e850bfc39600ce61d02b518de",
|
||||
"url": "https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp"
|
||||
}
|
||||
],
|
||||
"replicator": {
|
||||
"source": "replicator-source",
|
||||
"target": {
|
||||
"archive": "console-feed-3.2.2",
|
||||
"member": "package/lib/Transform/replicator/index.js",
|
||||
"sha256": "33ea546afdd46833594d7cdccbfc45dc654b8e9fa737d9ee5d940b6f164dba6b"
|
||||
},
|
||||
"upstream": {
|
||||
"archive": "replicator-1.0.1",
|
||||
"member": "package/index.js",
|
||||
"sha256": "7b0f488ae3581c23d252ac5c73fd6ae35884d876bfd8e186d23bbfa5847430d7"
|
||||
},
|
||||
"scope": "Modified fork of the replicator 1.0.x source family; the MIT notice is taken from 1.0.1, not a claim that npm 1.0.1 is installed or identical. The fixed console-feed TS revision compiles to the exact runtime before the original inline source map."
|
||||
},
|
||||
"stylis": {
|
||||
"source": "emotion-stylis-source",
|
||||
"target": {
|
||||
"archive": "%40emotion%2Fstylis-0.8.5",
|
||||
"member": "package/src/stylis.min.js",
|
||||
"sha256": "2d49f50cb973b395bb30ca1d03955599e6220dd347d57ae38324afe8c734506a"
|
||||
},
|
||||
"dependency": {
|
||||
"archive": "%40emotion%2Fstylis-0.8.5",
|
||||
"member": "package/package.json",
|
||||
"sha256": "1da8e474cb88a0070baa42cec78a3704dea0889c4decdb38d4e7b7489c83c8b0"
|
||||
},
|
||||
"dependencyVersion": "3.5.4",
|
||||
"recipe": "emotion-build",
|
||||
"scope": "Fixed tag commit source matches npm source exactly. Its original recipe modifies Stylis and calls an unversioned online Closure compiler; this earlier compiler stage was not rerun."
|
||||
},
|
||||
"hash": {
|
||||
"source": "smhasher",
|
||||
"notice": {
|
||||
"archive": "aappleby/smhasher@61a0530f28277f2e850bfc39600ce61d02b518de",
|
||||
"member": "src/MurmurHash2.cpp",
|
||||
"memberSha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
|
||||
"sourceSha256": "8cdec1fed73de41e4ee91ab78fe5ba76110582263064dcdcc0b770a25c0573f3",
|
||||
"start": "// MurmurHash2 was written by Austin Appleby, and is placed in the public",
|
||||
"end": "// domain. The author hereby disclaims copyright to this source code.\n",
|
||||
"source": "refactor/baselines/site-vendor/console-attribution/murmurhash2-public-domain.txt",
|
||||
"sha256": "50e13b0a1963f0b382255d2425df245dbdfd209201621e8c157687caedbbb949"
|
||||
},
|
||||
"reference": {
|
||||
"archive": "%40emotion%2Fhash-0.8.0",
|
||||
"member": "package/dist/hash.browser.esm.js",
|
||||
"sha256": "3f6d63bdf3241054ccac29fa5bad7ca228bb889a51214e22224a8fe8c6d3573d"
|
||||
},
|
||||
"references": [
|
||||
"https://github.com/garycourt/murmurhash-js",
|
||||
"61a0530f28277f2e850bfc39600ce61d02b518de"
|
||||
]
|
||||
},
|
||||
"cache": {
|
||||
"reference": {
|
||||
"archive": "%40emotion%2Fcache-10.0.29",
|
||||
"member": "package/dist/cache.browser.esm.js",
|
||||
"sha256": "7df64362f28f43e9af8dda5dc5edc2b3c4ecb094101f7c723bc9ef03f40767f0"
|
||||
},
|
||||
"upstreamUrl": "https://github.com/thysultan/stylis.js/tree/master/plugins/rule-sheet",
|
||||
"notice": "docs/licenses/console/stylis-rule-sheet/LICENSE"
|
||||
},
|
||||
"limitations": [
|
||||
"No replacement or execution of archived runtime libraries.",
|
||||
"Replicator is a modified fork; neither a unique npm fork base nor the entire original install lock is claimed.",
|
||||
"Emotion historical online Closure service was not re-executed; its published source is pinned to the matching upstream tag commit.",
|
||||
"Stack Overflow attribution and final remaining embedded-source review stay open."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"task": "SITE-07",
|
||||
"status": "checkpoint-incomplete",
|
||||
"recordedAt": "2026-09-14T23:49:08.277Z",
|
||||
"baseCommit": "d2a83f8a69c7a5d9a8bf30c9b370e573034f2000",
|
||||
"node": "v24.21.0",
|
||||
"sourceFingerprint": {
|
||||
"manifestSha256": "c0238bf1acb77ddf931c4b8702a1dc4d3ea341b525c23c78e000fff0d8109fec",
|
||||
"sourceRecordSha256": "d8d5237cf261177b571b07eec17acb11f7b3905a98a2aa0675b366b8d21d7b12",
|
||||
"consoleSha256": "5644af7bb35bb6d0bcfa7eeae9a21b406ac4fc1b499a6c797a6534c7d33f0678"
|
||||
},
|
||||
"unit": {
|
||||
"passed": 24,
|
||||
"failed": 0,
|
||||
"log": "refactor/.cache/console-derived-tests.log"
|
||||
},
|
||||
"reproduction": {
|
||||
"archives": 42,
|
||||
"exactModules": 100,
|
||||
"embeddedNotices": 2,
|
||||
"mappedMembers": 17,
|
||||
"transformedMembers": 7,
|
||||
"derivedGitSources": 5,
|
||||
"replicatorFork": true,
|
||||
"emotionStylisSource": true,
|
||||
"offlineLog": "refactor/.cache/console-derived-reproduce.log",
|
||||
"fetchLog": "refactor/.cache/console-derived-fetch.log",
|
||||
"licenseClosure": false
|
||||
},
|
||||
"browser": {
|
||||
"report": "refactor/.cache/browser/report.json",
|
||||
"sha256": "b902b3ac4e6f83a825112dda5f6ef815326c268893264c08d17bf2b44bb08cf0",
|
||||
"tests": [
|
||||
{
|
||||
"project": "chromium",
|
||||
"status": "passed",
|
||||
"retry": 0,
|
||||
"browser": "153.0.8010.12",
|
||||
"platform": "win32",
|
||||
"errors": [],
|
||||
"consoleErrors": [],
|
||||
"failedRequests": [
|
||||
{
|
||||
"url": "http://127.0.0.1:8084/test/pattern.mp4",
|
||||
"resourceType": "media",
|
||||
"failure": {
|
||||
"errorText": "net::ERR_ABORTED"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"project": "firefox",
|
||||
"status": "passed",
|
||||
"retry": 0,
|
||||
"browser": "155.0",
|
||||
"platform": "win32",
|
||||
"errors": [],
|
||||
"consoleErrors": [],
|
||||
"failedRequests": []
|
||||
},
|
||||
{
|
||||
"project": "webkit",
|
||||
"status": "passed",
|
||||
"retry": 0,
|
||||
"browser": "26.6",
|
||||
"platform": "win32",
|
||||
"errors": [],
|
||||
"consoleErrors": [],
|
||||
"failedRequests": []
|
||||
}
|
||||
],
|
||||
"noticeFilesPerEngine": 60
|
||||
},
|
||||
"checks": [
|
||||
"Strict docs-tools TypeScript",
|
||||
"Scoped source/test/maintenance ESLint",
|
||||
"Read-only console and site-notice generation checks"
|
||||
],
|
||||
"remaining": [
|
||||
"Component Stack Overflow attribution and final embedded-source review",
|
||||
"Other site asset provenance tasks"
|
||||
],
|
||||
"limits": [
|
||||
"Replicator is a modified source-family fork, not an unmodified npm 1.0.1 installation.",
|
||||
"Original Emotion online Closure compiler stage was not rerun; its generated source matches the immutable tag commit.",
|
||||
"No claim of the unique original full dependency lockfile.",
|
||||
"HTTPS integrations isolated; Windows local-page evidence does not replace physical-device or remote-publish validation.",
|
||||
"No runtime or lockfile changes, pushes, deployments or publications."
|
||||
]
|
||||
}
|
||||
@@ -30,11 +30,11 @@
|
||||
"Chromium copyright and full BSD conditions in console-feed source",
|
||||
"Sultan Tarimo MIT header in styled-components embedded rule-sheet source",
|
||||
"All seven linkifyjs simple-html-tokenizer files exactly reproduce from its fixed Git dependency with Babel 6.26.0; Yehuda Katz license preserved.",
|
||||
"All 17 react-inspector external source-map members exactly match Babel runtime 7.13.10 and regenerator-runtime 0.13.7; both licenses preserved."
|
||||
"All 17 react-inspector external source-map members exactly match Babel runtime 7.13.10 and regenerator-runtime 0.13.7; both licenses preserved.",
|
||||
"Modified replicator fork has fixed console-feed TS source matching the archived runtime, with Ivan Nikulin MIT attribution.",
|
||||
"Emotion Stylis pinned source and 3.5.4 dependency, rule-sheet source references, and MurmurHash references retain Sultan Tarimo, Gary Court and Austin Appleby notices; historical Closure stage not rerun."
|
||||
],
|
||||
"pending": [
|
||||
"console-feed replicator upstream attribution",
|
||||
"Emotion stylis/hash and cache rule-sheet attribution",
|
||||
"console-feed Component Stack Overflow attribution and any additional embedded sources"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
// this whole thing is a really fragile hack
|
||||
// but it works so ¯\_(ツ)_/¯
|
||||
|
||||
const stylisPath = require.resolve('stylis')
|
||||
const { promisify } = require('util')
|
||||
const j = require('jscodeshift')
|
||||
const request = require('request-promise-native')
|
||||
const fs = require('fs')
|
||||
const prettier = require('prettier')
|
||||
const recast = require('recast')
|
||||
|
||||
const readFile = promisify(fs.readFile)
|
||||
const writeFile = promisify(fs.writeFile)
|
||||
|
||||
const simplifySet = src =>
|
||||
j(src)
|
||||
.find(j.FunctionDeclaration, { id: { name: 'set' } })
|
||||
.forEach(path => {
|
||||
j(path).replaceWith(
|
||||
recast.parse(`function set(options) {
|
||||
var prefixOpt = options.prefix
|
||||
if (prefixOpt!==undefined) {
|
||||
should = null
|
||||
|
||||
if (!prefixOpt) {
|
||||
prefix = 0
|
||||
} else if (typeof prefixOpt !== 'function') {
|
||||
prefix = 1
|
||||
} else {
|
||||
prefix = 2
|
||||
should = prefixOpt
|
||||
}
|
||||
}
|
||||
return set
|
||||
}`).program.body[0]
|
||||
)
|
||||
})
|
||||
.toSource()
|
||||
|
||||
const removeOptions = src =>
|
||||
j(src)
|
||||
.find(j.SwitchStatement)
|
||||
.forEach(thing => {
|
||||
thing.value.cases = thing.value.cases.filter(node => {
|
||||
if (!node.test) return true
|
||||
switch (node.test.value) {
|
||||
case 'keyframe':
|
||||
case 'cascade':
|
||||
case 'preserve':
|
||||
case 'semicolon':
|
||||
case 'compress':
|
||||
case 'global': {
|
||||
return false
|
||||
}
|
||||
default: {
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.toSource()
|
||||
|
||||
const setOptions = src =>
|
||||
j(src)
|
||||
.find(j.VariableDeclarator)
|
||||
.forEach(path => {
|
||||
switch (path.value.id.name) {
|
||||
case 'escape':
|
||||
case 'keyed': {
|
||||
path.value.init.value = 0
|
||||
return
|
||||
}
|
||||
case 'semicolon': {
|
||||
path.value.init.value = 1
|
||||
}
|
||||
}
|
||||
})
|
||||
.toSource()
|
||||
|
||||
const removeUMDWrapper = src => {
|
||||
let code
|
||||
j(src)
|
||||
.find(j.FunctionExpression, { id: { name: 'factory' } })
|
||||
.forEach(path => {
|
||||
code = j(path).toSource()
|
||||
})
|
||||
.toSource()
|
||||
return "'use strict';\nwindow['stylis'] = " + code
|
||||
}
|
||||
|
||||
async function doThing() {
|
||||
const stylisSrc = (await readFile(stylisPath))
|
||||
.toString()
|
||||
.replace(
|
||||
'cascade + quote + bracket + atrule === 0 && id !== KEYFRAME && code !== SEMICOLON',
|
||||
'true === false'
|
||||
)
|
||||
.replace(
|
||||
'comment + quote + parentheses + bracket + semicolon === 0',
|
||||
'true === false'
|
||||
)
|
||||
.replace('switch (selector.charCodeAt(1))', 'switch (100)')
|
||||
.replace('(insert === 1)', '(true === false)')
|
||||
.replace('input.charCodeAt(9)*keyed', '0')
|
||||
.replace('switch (cascade + level) {', 'switch (2) {')
|
||||
.replace('compress*code === 0', 'true')
|
||||
.replace(`typeof(output = result) !== 'string'`, '(output = result)')
|
||||
// .replace("stylis['set'] = set", '')
|
||||
// .replace('set(options)', '')
|
||||
.replace('this !== void 0 && this.constructor === stylis', 'false')
|
||||
.replace('return factory(selector)', '')
|
||||
const result = removeUMDWrapper(
|
||||
simplifySet(setOptions(removeOptions(stylisSrc)))
|
||||
)
|
||||
// await writeFile('./src/stylis.js', result)
|
||||
console.log('start request')
|
||||
const data = (await request('https://closure-compiler.appspot.com/compile', {
|
||||
method: 'POST',
|
||||
form: {
|
||||
js_code: result,
|
||||
compilation_level: 'ADVANCED_OPTIMIZATIONS',
|
||||
output_format: 'text',
|
||||
output_info: 'compiled_code'
|
||||
}
|
||||
})).toString()
|
||||
|
||||
let finalSrc = data.replace('window.stylis=', 'export default ')
|
||||
|
||||
await writeFile(
|
||||
'./src/stylis.min.js',
|
||||
prettier.format(finalSrc, {
|
||||
semi: false,
|
||||
singleQuote: true
|
||||
})
|
||||
)
|
||||
|
||||
console.log('done')
|
||||
}
|
||||
|
||||
doThing()
|
||||
@@ -0,0 +1,625 @@
|
||||
export default function(W) {
|
||||
function M(d, c, e, h, a) {
|
||||
for (
|
||||
var m = 0,
|
||||
b = 0,
|
||||
v = 0,
|
||||
n = 0,
|
||||
q,
|
||||
g,
|
||||
x = 0,
|
||||
K = 0,
|
||||
k,
|
||||
u = (k = q = 0),
|
||||
l = 0,
|
||||
r = 0,
|
||||
I = 0,
|
||||
t = 0,
|
||||
B = e.length,
|
||||
J = B - 1,
|
||||
y,
|
||||
f = '',
|
||||
p = '',
|
||||
F = '',
|
||||
G = '',
|
||||
C;
|
||||
l < B;
|
||||
|
||||
) {
|
||||
g = e.charCodeAt(l)
|
||||
l === J &&
|
||||
0 !== b + n + v + m &&
|
||||
(0 !== b && (g = 47 === b ? 10 : 47), (n = v = m = 0), B++, J++)
|
||||
if (0 === b + n + v + m) {
|
||||
if (l === J && (0 < r && (f = f.replace(N, '')), 0 < f.trim().length)) {
|
||||
switch (g) {
|
||||
case 32:
|
||||
case 9:
|
||||
case 59:
|
||||
case 13:
|
||||
case 10:
|
||||
break
|
||||
default:
|
||||
f += e.charAt(l)
|
||||
}
|
||||
g = 59
|
||||
}
|
||||
switch (g) {
|
||||
case 123:
|
||||
f = f.trim()
|
||||
q = f.charCodeAt(0)
|
||||
k = 1
|
||||
for (t = ++l; l < B; ) {
|
||||
switch ((g = e.charCodeAt(l))) {
|
||||
case 123:
|
||||
k++
|
||||
break
|
||||
case 125:
|
||||
k--
|
||||
break
|
||||
case 47:
|
||||
switch ((g = e.charCodeAt(l + 1))) {
|
||||
case 42:
|
||||
case 47:
|
||||
a: {
|
||||
for (u = l + 1; u < J; ++u)
|
||||
switch (e.charCodeAt(u)) {
|
||||
case 47:
|
||||
if (
|
||||
42 === g &&
|
||||
42 === e.charCodeAt(u - 1) &&
|
||||
l + 2 !== u
|
||||
) {
|
||||
l = u + 1
|
||||
break a
|
||||
}
|
||||
break
|
||||
case 10:
|
||||
if (47 === g) {
|
||||
l = u + 1
|
||||
break a
|
||||
}
|
||||
}
|
||||
l = u
|
||||
}
|
||||
}
|
||||
break
|
||||
case 91:
|
||||
g++
|
||||
case 40:
|
||||
g++
|
||||
case 34:
|
||||
case 39:
|
||||
for (; l++ < J && e.charCodeAt(l) !== g; );
|
||||
}
|
||||
if (0 === k) break
|
||||
l++
|
||||
}
|
||||
k = e.substring(t, l)
|
||||
0 === q && (q = (f = f.replace(ca, '').trim()).charCodeAt(0))
|
||||
switch (q) {
|
||||
case 64:
|
||||
0 < r && (f = f.replace(N, ''))
|
||||
g = f.charCodeAt(1)
|
||||
switch (g) {
|
||||
case 100:
|
||||
case 109:
|
||||
case 115:
|
||||
case 45:
|
||||
r = c
|
||||
break
|
||||
default:
|
||||
r = O
|
||||
}
|
||||
k = M(c, r, k, g, a + 1)
|
||||
t = k.length
|
||||
0 < A &&
|
||||
((r = X(O, f, I)),
|
||||
(C = H(3, k, r, c, D, z, t, g, a, h)),
|
||||
(f = r.join('')),
|
||||
void 0 !== C &&
|
||||
0 === (t = (k = C.trim()).length) &&
|
||||
((g = 0), (k = '')))
|
||||
if (0 < t)
|
||||
switch (g) {
|
||||
case 115:
|
||||
f = f.replace(da, ea)
|
||||
case 100:
|
||||
case 109:
|
||||
case 45:
|
||||
k = f + '{' + k + '}'
|
||||
break
|
||||
case 107:
|
||||
f = f.replace(fa, '$1 $2')
|
||||
k = f + '{' + k + '}'
|
||||
k =
|
||||
1 === w || (2 === w && L('@' + k, 3))
|
||||
? '@-webkit-' + k + '@' + k
|
||||
: '@' + k
|
||||
break
|
||||
default:
|
||||
;(k = f + k), 112 === h && (k = ((p += k), ''))
|
||||
}
|
||||
else k = ''
|
||||
break
|
||||
default:
|
||||
k = M(c, X(c, f, I), k, h, a + 1)
|
||||
}
|
||||
F += k
|
||||
k = I = r = u = q = 0
|
||||
f = ''
|
||||
g = e.charCodeAt(++l)
|
||||
break
|
||||
case 125:
|
||||
case 59:
|
||||
f = (0 < r ? f.replace(N, '') : f).trim()
|
||||
if (1 < (t = f.length))
|
||||
switch (
|
||||
(0 === u &&
|
||||
((q = f.charCodeAt(0)), 45 === q || (96 < q && 123 > q)) &&
|
||||
(t = (f = f.replace(' ', ':')).length),
|
||||
0 < A &&
|
||||
void 0 !== (C = H(1, f, c, d, D, z, p.length, h, a, h)) &&
|
||||
0 === (t = (f = C.trim()).length) &&
|
||||
(f = '\x00\x00'),
|
||||
(q = f.charCodeAt(0)),
|
||||
(g = f.charCodeAt(1)),
|
||||
q)
|
||||
) {
|
||||
case 0:
|
||||
break
|
||||
case 64:
|
||||
if (105 === g || 99 === g) {
|
||||
G += f + e.charAt(l)
|
||||
break
|
||||
}
|
||||
default:
|
||||
58 !== f.charCodeAt(t - 1) &&
|
||||
(p += P(f, q, g, f.charCodeAt(2)))
|
||||
}
|
||||
I = r = u = q = 0
|
||||
f = ''
|
||||
g = e.charCodeAt(++l)
|
||||
}
|
||||
}
|
||||
switch (g) {
|
||||
case 13:
|
||||
case 10:
|
||||
47 === b
|
||||
? (b = 0)
|
||||
: 0 === 1 + q &&
|
||||
107 !== h &&
|
||||
0 < f.length &&
|
||||
((r = 1), (f += '\x00'))
|
||||
0 < A * Y && H(0, f, c, d, D, z, p.length, h, a, h)
|
||||
z = 1
|
||||
D++
|
||||
break
|
||||
case 59:
|
||||
case 125:
|
||||
if (0 === b + n + v + m) {
|
||||
z++
|
||||
break
|
||||
}
|
||||
default:
|
||||
z++
|
||||
y = e.charAt(l)
|
||||
switch (g) {
|
||||
case 9:
|
||||
case 32:
|
||||
if (0 === n + m + b)
|
||||
switch (x) {
|
||||
case 44:
|
||||
case 58:
|
||||
case 9:
|
||||
case 32:
|
||||
y = ''
|
||||
break
|
||||
default:
|
||||
32 !== g && (y = ' ')
|
||||
}
|
||||
break
|
||||
case 0:
|
||||
y = '\\0'
|
||||
break
|
||||
case 12:
|
||||
y = '\\f'
|
||||
break
|
||||
case 11:
|
||||
y = '\\v'
|
||||
break
|
||||
case 38:
|
||||
0 === n + b + m && ((r = I = 1), (y = '\f' + y))
|
||||
break
|
||||
case 108:
|
||||
if (0 === n + b + m + E && 0 < u)
|
||||
switch (l - u) {
|
||||
case 2:
|
||||
112 === x && 58 === e.charCodeAt(l - 3) && (E = x)
|
||||
case 8:
|
||||
111 === K && (E = K)
|
||||
}
|
||||
break
|
||||
case 58:
|
||||
0 === n + b + m && (u = l)
|
||||
break
|
||||
case 44:
|
||||
0 === b + v + n + m && ((r = 1), (y += '\r'))
|
||||
break
|
||||
case 34:
|
||||
case 39:
|
||||
0 === b && (n = n === g ? 0 : 0 === n ? g : n)
|
||||
break
|
||||
case 91:
|
||||
0 === n + b + v && m++
|
||||
break
|
||||
case 93:
|
||||
0 === n + b + v && m--
|
||||
break
|
||||
case 41:
|
||||
0 === n + b + m && v--
|
||||
break
|
||||
case 40:
|
||||
if (0 === n + b + m) {
|
||||
if (0 === q)
|
||||
switch (2 * x + 3 * K) {
|
||||
case 533:
|
||||
break
|
||||
default:
|
||||
q = 1
|
||||
}
|
||||
v++
|
||||
}
|
||||
break
|
||||
case 64:
|
||||
0 === b + v + n + m + u + k && (k = 1)
|
||||
break
|
||||
case 42:
|
||||
case 47:
|
||||
if (!(0 < n + m + v))
|
||||
switch (b) {
|
||||
case 0:
|
||||
switch (2 * g + 3 * e.charCodeAt(l + 1)) {
|
||||
case 235:
|
||||
b = 47
|
||||
break
|
||||
case 220:
|
||||
;(t = l), (b = 42)
|
||||
}
|
||||
break
|
||||
case 42:
|
||||
47 === g &&
|
||||
42 === x &&
|
||||
t + 2 !== l &&
|
||||
(33 === e.charCodeAt(t + 2) &&
|
||||
(p += e.substring(t, l + 1)),
|
||||
(y = ''),
|
||||
(b = 0))
|
||||
}
|
||||
}
|
||||
0 === b && (f += y)
|
||||
}
|
||||
K = x
|
||||
x = g
|
||||
l++
|
||||
}
|
||||
t = p.length
|
||||
if (0 < t) {
|
||||
r = c
|
||||
if (
|
||||
0 < A &&
|
||||
((C = H(2, p, r, d, D, z, t, h, a, h)),
|
||||
void 0 !== C && 0 === (p = C).length)
|
||||
)
|
||||
return G + p + F
|
||||
p = r.join(',') + '{' + p + '}'
|
||||
if (0 !== w * E) {
|
||||
2 !== w || L(p, 2) || (E = 0)
|
||||
switch (E) {
|
||||
case 111:
|
||||
p = p.replace(ha, ':-moz-$1') + p
|
||||
break
|
||||
case 112:
|
||||
p =
|
||||
p.replace(Q, '::-webkit-input-$1') +
|
||||
p.replace(Q, '::-moz-$1') +
|
||||
p.replace(Q, ':-ms-input-$1') +
|
||||
p
|
||||
}
|
||||
E = 0
|
||||
}
|
||||
}
|
||||
return G + p + F
|
||||
}
|
||||
function X(d, c, e) {
|
||||
var h = c.trim().split(ia)
|
||||
c = h
|
||||
var a = h.length,
|
||||
m = d.length
|
||||
switch (m) {
|
||||
case 0:
|
||||
case 1:
|
||||
var b = 0
|
||||
for (d = 0 === m ? '' : d[0] + ' '; b < a; ++b)
|
||||
c[b] = Z(d, c[b], e, m).trim()
|
||||
break
|
||||
default:
|
||||
var v = (b = 0)
|
||||
for (c = []; b < a; ++b)
|
||||
for (var n = 0; n < m; ++n) c[v++] = Z(d[n] + ' ', h[b], e, m).trim()
|
||||
}
|
||||
return c
|
||||
}
|
||||
function Z(d, c, e) {
|
||||
var h = c.charCodeAt(0)
|
||||
33 > h && (h = (c = c.trim()).charCodeAt(0))
|
||||
switch (h) {
|
||||
case 38:
|
||||
return c.replace(F, '$1' + d.trim())
|
||||
case 58:
|
||||
return d.trim() + c.replace(F, '$1' + d.trim())
|
||||
default:
|
||||
if (0 < 1 * e && 0 < c.indexOf('\f'))
|
||||
return c.replace(F, (58 === d.charCodeAt(0) ? '' : '$1') + d.trim())
|
||||
}
|
||||
return d + c
|
||||
}
|
||||
function P(d, c, e, h) {
|
||||
var a = d + ';',
|
||||
m = 2 * c + 3 * e + 4 * h
|
||||
if (944 === m) {
|
||||
d = a.indexOf(':', 9) + 1
|
||||
var b = a.substring(d, a.length - 1).trim()
|
||||
b = a.substring(0, d).trim() + b + ';'
|
||||
return 1 === w || (2 === w && L(b, 1)) ? '-webkit-' + b + b : b
|
||||
}
|
||||
if (0 === w || (2 === w && !L(a, 1))) return a
|
||||
switch (m) {
|
||||
case 1015:
|
||||
return 97 === a.charCodeAt(10) ? '-webkit-' + a + a : a
|
||||
case 951:
|
||||
return 116 === a.charCodeAt(3) ? '-webkit-' + a + a : a
|
||||
case 963:
|
||||
return 110 === a.charCodeAt(5) ? '-webkit-' + a + a : a
|
||||
case 1009:
|
||||
if (100 !== a.charCodeAt(4)) break
|
||||
case 969:
|
||||
case 942:
|
||||
return '-webkit-' + a + a
|
||||
case 978:
|
||||
return '-webkit-' + a + '-moz-' + a + a
|
||||
case 1019:
|
||||
case 983:
|
||||
return '-webkit-' + a + '-moz-' + a + '-ms-' + a + a
|
||||
case 883:
|
||||
if (45 === a.charCodeAt(8)) return '-webkit-' + a + a
|
||||
if (0 < a.indexOf('image-set(', 11))
|
||||
return a.replace(ja, '$1-webkit-$2') + a
|
||||
break
|
||||
case 932:
|
||||
if (45 === a.charCodeAt(4))
|
||||
switch (a.charCodeAt(5)) {
|
||||
case 103:
|
||||
return (
|
||||
'-webkit-box-' +
|
||||
a.replace('-grow', '') +
|
||||
'-webkit-' +
|
||||
a +
|
||||
'-ms-' +
|
||||
a.replace('grow', 'positive') +
|
||||
a
|
||||
)
|
||||
case 115:
|
||||
return (
|
||||
'-webkit-' + a + '-ms-' + a.replace('shrink', 'negative') + a
|
||||
)
|
||||
case 98:
|
||||
return (
|
||||
'-webkit-' +
|
||||
a +
|
||||
'-ms-' +
|
||||
a.replace('basis', 'preferred-size') +
|
||||
a
|
||||
)
|
||||
}
|
||||
return '-webkit-' + a + '-ms-' + a + a
|
||||
case 964:
|
||||
return '-webkit-' + a + '-ms-flex-' + a + a
|
||||
case 1023:
|
||||
if (99 !== a.charCodeAt(8)) break
|
||||
b = a
|
||||
.substring(a.indexOf(':', 15))
|
||||
.replace('flex-', '')
|
||||
.replace('space-between', 'justify')
|
||||
return '-webkit-box-pack' + b + '-webkit-' + a + '-ms-flex-pack' + b + a
|
||||
case 1005:
|
||||
return ka.test(a)
|
||||
? a.replace(aa, ':-webkit-') + a.replace(aa, ':-moz-') + a
|
||||
: a
|
||||
case 1e3:
|
||||
b = a.substring(13).trim()
|
||||
c = b.indexOf('-') + 1
|
||||
switch (b.charCodeAt(0) + b.charCodeAt(c)) {
|
||||
case 226:
|
||||
b = a.replace(G, 'tb')
|
||||
break
|
||||
case 232:
|
||||
b = a.replace(G, 'tb-rl')
|
||||
break
|
||||
case 220:
|
||||
b = a.replace(G, 'lr')
|
||||
break
|
||||
default:
|
||||
return a
|
||||
}
|
||||
return '-webkit-' + a + '-ms-' + b + a
|
||||
case 1017:
|
||||
if (-1 === a.indexOf('sticky', 9)) break
|
||||
case 975:
|
||||
c = (a = d).length - 10
|
||||
b = (33 === a.charCodeAt(c) ? a.substring(0, c) : a)
|
||||
.substring(d.indexOf(':', 7) + 1)
|
||||
.trim()
|
||||
switch ((m = b.charCodeAt(0) + (b.charCodeAt(7) | 0))) {
|
||||
case 203:
|
||||
if (111 > b.charCodeAt(8)) break
|
||||
case 115:
|
||||
a = a.replace(b, '-webkit-' + b) + ';' + a
|
||||
break
|
||||
case 207:
|
||||
case 102:
|
||||
a =
|
||||
a.replace(b, '-webkit-' + (102 < m ? 'inline-' : '') + 'box') +
|
||||
';' +
|
||||
a.replace(b, '-webkit-' + b) +
|
||||
';' +
|
||||
a.replace(b, '-ms-' + b + 'box') +
|
||||
';' +
|
||||
a
|
||||
}
|
||||
return a + ';'
|
||||
case 938:
|
||||
if (45 === a.charCodeAt(5))
|
||||
switch (a.charCodeAt(6)) {
|
||||
case 105:
|
||||
return (
|
||||
(b = a.replace('-items', '')),
|
||||
'-webkit-' + a + '-webkit-box-' + b + '-ms-flex-' + b + a
|
||||
)
|
||||
case 115:
|
||||
return '-webkit-' + a + '-ms-flex-item-' + a.replace(ba, '') + a
|
||||
default:
|
||||
return (
|
||||
'-webkit-' +
|
||||
a +
|
||||
'-ms-flex-line-pack' +
|
||||
a.replace('align-content', '').replace(ba, '') +
|
||||
a
|
||||
)
|
||||
}
|
||||
break
|
||||
case 973:
|
||||
case 989:
|
||||
if (45 !== a.charCodeAt(3) || 122 === a.charCodeAt(4)) break
|
||||
case 931:
|
||||
case 953:
|
||||
if (!0 === la.test(d))
|
||||
return 115 === (b = d.substring(d.indexOf(':') + 1)).charCodeAt(0)
|
||||
? P(d.replace('stretch', 'fill-available'), c, e, h).replace(
|
||||
':fill-available',
|
||||
':stretch'
|
||||
)
|
||||
: a.replace(b, '-webkit-' + b) +
|
||||
a.replace(b, '-moz-' + b.replace('fill-', '')) +
|
||||
a
|
||||
break
|
||||
case 962:
|
||||
if (
|
||||
((a =
|
||||
'-webkit-' + a + (102 === a.charCodeAt(5) ? '-ms-' + a : '') + a),
|
||||
211 === e + h &&
|
||||
105 === a.charCodeAt(13) &&
|
||||
0 < a.indexOf('transform', 10))
|
||||
)
|
||||
return (
|
||||
a.substring(0, a.indexOf(';', 27) + 1).replace(ma, '$1-webkit-$2') +
|
||||
a
|
||||
)
|
||||
}
|
||||
return a
|
||||
}
|
||||
function L(d, c) {
|
||||
var e = d.indexOf(1 === c ? ':' : '{'),
|
||||
h = d.substring(0, 3 !== c ? e : 10)
|
||||
e = d.substring(e + 1, d.length - 1)
|
||||
return R(2 !== c ? h : h.replace(na, '$1'), e, c)
|
||||
}
|
||||
function ea(d, c) {
|
||||
var e = P(c, c.charCodeAt(0), c.charCodeAt(1), c.charCodeAt(2))
|
||||
return e !== c + ';'
|
||||
? e.replace(oa, ' or ($1)').substring(4)
|
||||
: '(' + c + ')'
|
||||
}
|
||||
function H(d, c, e, h, a, m, b, v, n, q) {
|
||||
for (var g = 0, x = c, w; g < A; ++g)
|
||||
switch ((w = S[g].call(B, d, x, e, h, a, m, b, v, n, q))) {
|
||||
case void 0:
|
||||
case !1:
|
||||
case !0:
|
||||
case null:
|
||||
break
|
||||
default:
|
||||
x = w
|
||||
}
|
||||
if (x !== c) return x
|
||||
}
|
||||
function T(d) {
|
||||
switch (d) {
|
||||
case void 0:
|
||||
case null:
|
||||
A = S.length = 0
|
||||
break
|
||||
default:
|
||||
if ('function' === typeof d) S[A++] = d
|
||||
else if ('object' === typeof d)
|
||||
for (var c = 0, e = d.length; c < e; ++c) T(d[c])
|
||||
else Y = !!d | 0
|
||||
}
|
||||
return T
|
||||
}
|
||||
function U(d) {
|
||||
d = d.prefix
|
||||
void 0 !== d &&
|
||||
((R = null),
|
||||
d ? ('function' !== typeof d ? (w = 1) : ((w = 2), (R = d))) : (w = 0))
|
||||
return U
|
||||
}
|
||||
function B(d, c) {
|
||||
var e = d
|
||||
33 > e.charCodeAt(0) && (e = e.trim())
|
||||
V = e
|
||||
e = [V]
|
||||
if (0 < A) {
|
||||
var h = H(-1, c, e, e, D, z, 0, 0, 0, 0)
|
||||
void 0 !== h && 'string' === typeof h && (c = h)
|
||||
}
|
||||
var a = M(O, e, c, 0, 0)
|
||||
0 < A &&
|
||||
((h = H(-2, a, e, e, D, z, a.length, 0, 0, 0)), void 0 !== h && (a = h))
|
||||
V = ''
|
||||
E = 0
|
||||
z = D = 1
|
||||
return a
|
||||
}
|
||||
var ca = /^\0+/g,
|
||||
N = /[\0\r\f]/g,
|
||||
aa = /: */g,
|
||||
ka = /zoo|gra/,
|
||||
ma = /([,: ])(transform)/g,
|
||||
ia = /,\r+?/g,
|
||||
F = /([\t\r\n ])*\f?&/g,
|
||||
fa = /@(k\w+)\s*(\S*)\s*/,
|
||||
Q = /::(place)/g,
|
||||
ha = /:(read-only)/g,
|
||||
G = /[svh]\w+-[tblr]{2}/,
|
||||
da = /\(\s*(.*)\s*\)/g,
|
||||
oa = /([\s\S]*?);/g,
|
||||
ba = /-self|flex-/g,
|
||||
na = /[^]*?(:[rp][el]a[\w-]+)[^]*/,
|
||||
la = /stretch|:\s*\w+\-(?:conte|avail)/,
|
||||
ja = /([^-])(image-set\()/,
|
||||
z = 1,
|
||||
D = 1,
|
||||
E = 0,
|
||||
w = 1,
|
||||
O = [],
|
||||
S = [],
|
||||
A = 0,
|
||||
R = null,
|
||||
Y = 0,
|
||||
V = ''
|
||||
B.use = T
|
||||
B.set = U
|
||||
void 0 !== W && U(W)
|
||||
return B
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# MurmurHash.js
|
||||
|
||||
An optimized JavaScript implementation of the MurmurHash algorithms.
|
||||
|
||||
These algorithms take a JavaScript string (and a seed), and quickly create a non-cryptographic 32-bit hash from it. And by quick I mean sub-millisecond performance.
|
||||
|
||||
More information about these algorithms can be found at:
|
||||
|
||||
* [MurmurHash Homepage](http://sites.google.com/site/murmurhash/)
|
||||
* [Wikipedia Entry on MurmurHash](http://en.wikipedia.org/wiki/MurmurHash)
|
||||
|
||||
## License (MIT)
|
||||
|
||||
Copyright (c) 2011 Gary Court
|
||||
|
||||
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, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,2 @@
|
||||
// MurmurHash2 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin)
|
||||
|
||||
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, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -0,0 +1,588 @@
|
||||
// Const
|
||||
const TRANSFORMED_TYPE_KEY = '@t'
|
||||
const CIRCULAR_REF_KEY = '@r'
|
||||
const KEY_REQUIRE_ESCAPING_RE = /^#*@(t|r)$/
|
||||
|
||||
const GLOBAL = (function getGlobal() {
|
||||
// NOTE: see http://www.ecma-international.org/ecma-262/6.0/index.html#sec-performeval step 10
|
||||
const savedEval = eval
|
||||
|
||||
return savedEval('this')
|
||||
})()
|
||||
|
||||
const ARRAY_BUFFER_SUPPORTED = typeof ArrayBuffer === 'function'
|
||||
const MAP_SUPPORTED = typeof Map === 'function'
|
||||
const SET_SUPPORTED = typeof Set === 'function'
|
||||
|
||||
const TYPED_ARRAY_CTORS = [
|
||||
'Int8Array',
|
||||
'Uint8Array',
|
||||
'Uint8ClampedArray',
|
||||
'Int16Array',
|
||||
'Uint16Array',
|
||||
'Int32Array',
|
||||
'Uint32Array',
|
||||
'Float32Array',
|
||||
'Float64Array',
|
||||
]
|
||||
|
||||
// Saved proto functions
|
||||
const arrSlice = Array.prototype.slice
|
||||
|
||||
// Default serializer
|
||||
const JSONSerializer = {
|
||||
serialize(val: any) {
|
||||
return JSON.stringify(val)
|
||||
},
|
||||
|
||||
deserialize(val: any) {
|
||||
return JSON.parse(val)
|
||||
},
|
||||
}
|
||||
|
||||
// EncodingTransformer
|
||||
class EncodingTransformer {
|
||||
references: any
|
||||
transforms: any
|
||||
circularCandidates: any
|
||||
circularCandidatesDescrs: any
|
||||
circularRefCount: any
|
||||
|
||||
constructor(val: any, transforms: any) {
|
||||
this.references = val
|
||||
this.transforms = transforms
|
||||
this.circularCandidates = []
|
||||
this.circularCandidatesDescrs = []
|
||||
this.circularRefCount = 0
|
||||
}
|
||||
|
||||
static _createRefMark(idx: any) {
|
||||
const obj = Object.create(null)
|
||||
|
||||
obj[CIRCULAR_REF_KEY] = idx
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
_createCircularCandidate(val: any, parent: any, key: any) {
|
||||
this.circularCandidates.push(val)
|
||||
this.circularCandidatesDescrs.push({ parent, key, refIdx: -1 })
|
||||
}
|
||||
|
||||
_applyTransform(val: any, parent: any, key: any, transform: any) {
|
||||
const result = Object.create(null)
|
||||
const serializableVal = transform.toSerializable(val)
|
||||
|
||||
if (typeof serializableVal === 'object')
|
||||
this._createCircularCandidate(val, parent, key)
|
||||
|
||||
result[TRANSFORMED_TYPE_KEY] = transform.type
|
||||
result.data = this._handleValue(() => serializableVal, parent, key)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
_handleArray(arr: any): any {
|
||||
const result = [] as any
|
||||
|
||||
for (let i = 0; i < arr.length; i++)
|
||||
result[i] = this._handleValue(() => arr[i], result, i)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
_handlePlainObject(obj: any) {
|
||||
const result = Object.create(null)
|
||||
|
||||
for (const key in obj) {
|
||||
if (Reflect.has(obj, key)) {
|
||||
const resultKey = KEY_REQUIRE_ESCAPING_RE.test(key) ? `#${key}` : key
|
||||
|
||||
result[resultKey] = this._handleValue(() => obj[key], result, resultKey)
|
||||
}
|
||||
}
|
||||
|
||||
const name = obj?.__proto__?.constructor?.name
|
||||
if (name && name !== 'Object') {
|
||||
result.constructor = { name }
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
_handleObject(obj: any, parent: any, key: any) {
|
||||
this._createCircularCandidate(obj, parent, key)
|
||||
|
||||
return Array.isArray(obj)
|
||||
? this._handleArray(obj)
|
||||
: this._handlePlainObject(obj)
|
||||
}
|
||||
|
||||
_ensureCircularReference(obj: any) {
|
||||
const circularCandidateIdx = this.circularCandidates.indexOf(obj)
|
||||
|
||||
if (circularCandidateIdx > -1) {
|
||||
const descr = this.circularCandidatesDescrs[circularCandidateIdx]
|
||||
|
||||
if (descr.refIdx === -1)
|
||||
descr.refIdx = descr.parent ? ++this.circularRefCount : 0
|
||||
|
||||
return EncodingTransformer._createRefMark(descr.refIdx)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
_handleValue(getVal: () => any, parent: any, key: any) {
|
||||
try {
|
||||
const val = getVal()
|
||||
const type = typeof val
|
||||
const isObject = type === 'object' && val !== null
|
||||
|
||||
if (isObject) {
|
||||
const refMark = this._ensureCircularReference(val)
|
||||
|
||||
if (refMark) return refMark
|
||||
}
|
||||
|
||||
for (const transform of this.transforms) {
|
||||
if (transform.shouldTransform(type, val))
|
||||
return this._applyTransform(val, parent, key, transform)
|
||||
}
|
||||
|
||||
if (isObject) return this._handleObject(val, parent, key)
|
||||
|
||||
return val
|
||||
} catch (e) {
|
||||
try {
|
||||
return this._handleValue(
|
||||
() => (e instanceof Error ? e : new Error(e)),
|
||||
parent,
|
||||
key
|
||||
)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform() {
|
||||
const references = [this._handleValue(() => this.references, null, null)]
|
||||
|
||||
for (const descr of this.circularCandidatesDescrs) {
|
||||
if (descr.refIdx > 0) {
|
||||
references[descr.refIdx] = descr.parent[descr.key]
|
||||
descr.parent[descr.key] = EncodingTransformer._createRefMark(
|
||||
descr.refIdx
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return references
|
||||
}
|
||||
}
|
||||
|
||||
// DecodingTransform
|
||||
class DecodingTransformer {
|
||||
references: any
|
||||
transformMap: any
|
||||
activeTransformsStack = [] as any
|
||||
visitedRefs = Object.create(null)
|
||||
|
||||
constructor(references: any, transformsMap: any) {
|
||||
this.references = references
|
||||
this.transformMap = transformsMap
|
||||
}
|
||||
|
||||
_handlePlainObject(obj: any) {
|
||||
const unescaped = Object.create(null)
|
||||
|
||||
if ('constructor' in obj) {
|
||||
if (!obj.constructor || typeof obj.constructor.name !== 'string') {
|
||||
obj.constructor = {
|
||||
name: 'Object',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
this._handleValue(obj[key], obj, key)
|
||||
|
||||
if (KEY_REQUIRE_ESCAPING_RE.test(key)) {
|
||||
// NOTE: use intermediate object to avoid unescaped and escaped keys interference
|
||||
// E.g. unescaped "##@t" will be "#@t" which can overwrite escaped "#@t".
|
||||
unescaped[key.substring(1)] = obj[key]
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const unsecapedKey in unescaped)
|
||||
obj[unsecapedKey] = unescaped[unsecapedKey]
|
||||
}
|
||||
|
||||
_handleTransformedObject(obj: any, parent: any, key: any) {
|
||||
const transformType = obj[TRANSFORMED_TYPE_KEY]
|
||||
const transform = this.transformMap[transformType]
|
||||
|
||||
if (!transform)
|
||||
throw new Error(`Can't find transform for "${transformType}" type.`)
|
||||
|
||||
this.activeTransformsStack.push(obj)
|
||||
this._handleValue(obj.data, obj, 'data')
|
||||
this.activeTransformsStack.pop()
|
||||
|
||||
parent[key] = transform.fromSerializable(obj.data)
|
||||
}
|
||||
|
||||
_handleCircularSelfRefDuringTransform(refIdx: any, parent: any, key: any) {
|
||||
// NOTE: we've hit a hard case: object reference itself during transformation.
|
||||
// We can't dereference it since we don't have resulting object yet. And we'll
|
||||
// not be able to restore reference lately because we will need to traverse
|
||||
// transformed object again and reference might be unreachable or new object contain
|
||||
// new circular references. As a workaround we create getter, so once transformation
|
||||
// complete, dereferenced property will point to correct transformed object.
|
||||
const references = this.references
|
||||
|
||||
Object.defineProperty(parent, key, {
|
||||
// @ts-ignore
|
||||
val: void 0,
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
|
||||
get() {
|
||||
if (this.val === void 0) this.val = references[refIdx]
|
||||
|
||||
return (<any>this).val
|
||||
},
|
||||
|
||||
set(value) {
|
||||
this.val = value
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
_handleCircularRef(refIdx: any, parent: any, key: any) {
|
||||
if (this.activeTransformsStack.includes(this.references[refIdx]))
|
||||
this._handleCircularSelfRefDuringTransform(refIdx, parent, key)
|
||||
else {
|
||||
if (!this.visitedRefs[refIdx]) {
|
||||
this.visitedRefs[refIdx] = true
|
||||
this._handleValue(this.references[refIdx], this.references, refIdx)
|
||||
}
|
||||
|
||||
parent[key] = this.references[refIdx]
|
||||
}
|
||||
}
|
||||
|
||||
_handleValue(val: any, parent: any, key: any) {
|
||||
if (typeof val !== 'object' || val === null) return
|
||||
|
||||
const refIdx = val[CIRCULAR_REF_KEY]
|
||||
|
||||
if (refIdx !== void 0) this._handleCircularRef(refIdx, parent, key)
|
||||
else if (val[TRANSFORMED_TYPE_KEY])
|
||||
this._handleTransformedObject(val, parent, key)
|
||||
else if (Array.isArray(val)) {
|
||||
for (let i = 0; i < val.length; i++) this._handleValue(val[i], val, i)
|
||||
} else this._handlePlainObject(val)
|
||||
}
|
||||
|
||||
transform() {
|
||||
this.visitedRefs[0] = true
|
||||
this._handleValue(this.references[0], this.references, 0)
|
||||
|
||||
return this.references[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Transforms
|
||||
const builtInTransforms = [
|
||||
{
|
||||
type: '[[NaN]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return type === 'number' && isNaN(val)
|
||||
},
|
||||
|
||||
toSerializable() {
|
||||
return ''
|
||||
},
|
||||
|
||||
fromSerializable() {
|
||||
return NaN
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[undefined]]',
|
||||
|
||||
shouldTransform(type: any) {
|
||||
return type === 'undefined'
|
||||
},
|
||||
|
||||
toSerializable() {
|
||||
return ''
|
||||
},
|
||||
|
||||
fromSerializable() {
|
||||
return void 0
|
||||
},
|
||||
},
|
||||
{
|
||||
type: '[[Date]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return val instanceof Date
|
||||
},
|
||||
|
||||
toSerializable(date: any) {
|
||||
return date.getTime()
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
const date = new Date()
|
||||
|
||||
date.setTime(val)
|
||||
return date
|
||||
},
|
||||
},
|
||||
{
|
||||
type: '[[RegExp]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return val instanceof RegExp
|
||||
},
|
||||
|
||||
toSerializable(re: any) {
|
||||
const result = {
|
||||
src: re.source,
|
||||
flags: '',
|
||||
}
|
||||
|
||||
if (re.global) result.flags += 'g'
|
||||
|
||||
if (re.ignoreCase) result.flags += 'i'
|
||||
|
||||
if (re.multiline) result.flags += 'm'
|
||||
|
||||
return result
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
return new RegExp(val.src, val.flags)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[Error]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return val instanceof Error
|
||||
},
|
||||
|
||||
toSerializable(err: any) {
|
||||
if (!err.stack) {
|
||||
;(Error as any).captureStackTrace?.(err)
|
||||
}
|
||||
|
||||
return {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
}
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
const Ctor = GLOBAL[val.name] || Error
|
||||
const err = new Ctor(val.message)
|
||||
|
||||
err.stack = val.stack
|
||||
return err
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[ArrayBuffer]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return ARRAY_BUFFER_SUPPORTED && val instanceof ArrayBuffer
|
||||
},
|
||||
|
||||
toSerializable(buffer: any) {
|
||||
const view = new Int8Array(buffer)
|
||||
|
||||
return arrSlice.call(view)
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
if (ARRAY_BUFFER_SUPPORTED) {
|
||||
const buffer = new ArrayBuffer(val.length)
|
||||
const view = new Int8Array(buffer)
|
||||
|
||||
view.set(val)
|
||||
|
||||
return buffer
|
||||
}
|
||||
|
||||
return val
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[TypedArray]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
for (const ctorName of TYPED_ARRAY_CTORS) {
|
||||
if (
|
||||
typeof GLOBAL[ctorName] === 'function' &&
|
||||
val instanceof GLOBAL[ctorName]
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
toSerializable(arr: any) {
|
||||
return {
|
||||
ctorName: arr.constructor.name,
|
||||
arr: arrSlice.call(arr),
|
||||
}
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
return typeof GLOBAL[val.ctorName] === 'function'
|
||||
? new GLOBAL[val.ctorName](val.arr)
|
||||
: val.arr
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[Map]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return MAP_SUPPORTED && val instanceof Map
|
||||
},
|
||||
|
||||
toSerializable(map: any) {
|
||||
const flattenedKVArr: any = []
|
||||
|
||||
map.forEach((val: any, key: any) => {
|
||||
flattenedKVArr.push(key)
|
||||
flattenedKVArr.push(val)
|
||||
})
|
||||
|
||||
return flattenedKVArr
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
if (MAP_SUPPORTED) {
|
||||
// NOTE: new Map(iterable) is not supported by all browsers
|
||||
const map = new Map()
|
||||
|
||||
for (var i = 0; i < val.length; i += 2) map.set(val[i], val[i + 1])
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
const kvArr = []
|
||||
|
||||
// @ts-ignore
|
||||
for (let j = 0; j < val.length; j += 2) kvArr.push([val[i], val[i + 1]])
|
||||
|
||||
return kvArr
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
type: '[[Set]]',
|
||||
|
||||
shouldTransform(type: any, val: any) {
|
||||
return SET_SUPPORTED && val instanceof Set
|
||||
},
|
||||
|
||||
toSerializable(set: any) {
|
||||
const arr: any = []
|
||||
|
||||
set.forEach((val: any) => {
|
||||
arr.push(val)
|
||||
})
|
||||
|
||||
return arr
|
||||
},
|
||||
|
||||
fromSerializable(val: any) {
|
||||
if (SET_SUPPORTED) {
|
||||
// NOTE: new Set(iterable) is not supported by all browsers
|
||||
const set = new Set()
|
||||
|
||||
for (let i = 0; i < val.length; i++) set.add(val[i])
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
return val
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// Replicator
|
||||
class Replicator {
|
||||
transforms = [] as any
|
||||
transformsMap = Object.create(null)
|
||||
serializer: any
|
||||
|
||||
constructor(serializer?: any) {
|
||||
this.serializer = serializer || JSONSerializer
|
||||
|
||||
this.addTransforms(builtInTransforms)
|
||||
}
|
||||
|
||||
addTransforms(transforms: any) {
|
||||
transforms = Array.isArray(transforms) ? transforms : [transforms]
|
||||
|
||||
for (const transform of transforms) {
|
||||
if (this.transformsMap[transform.type])
|
||||
throw new Error(
|
||||
`Transform with type "${transform.type}" was already added.`
|
||||
)
|
||||
|
||||
this.transforms.push(transform)
|
||||
this.transformsMap[transform.type] = transform
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
removeTransforms(transforms: any) {
|
||||
transforms = Array.isArray(transforms) ? transforms : [transforms]
|
||||
|
||||
for (const transform of transforms) {
|
||||
const idx = this.transforms.indexOf(transform)
|
||||
|
||||
if (idx > -1) this.transforms.splice(idx, 1)
|
||||
|
||||
delete this.transformsMap[transform.type]
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
encode(val: any) {
|
||||
const transformer = new EncodingTransformer(val, this.transforms)
|
||||
const references = transformer.transform()
|
||||
|
||||
return this.serializer.serialize(references)
|
||||
}
|
||||
|
||||
decode(val: any) {
|
||||
const references = this.serializer.deserialize(val)
|
||||
const transformer = new DecodingTransformer(references, this.transformsMap)
|
||||
|
||||
return transformer.transform()
|
||||
}
|
||||
}
|
||||
|
||||
export default Replicator
|
||||
@@ -0,0 +1,523 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHash2 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
|
||||
// Note - This code makes a few assumptions about how your machine behaves -
|
||||
|
||||
// 1. We can read a 4-byte value from any address without crashing
|
||||
// 2. sizeof(int) == 4
|
||||
|
||||
// And it has a few limitations -
|
||||
|
||||
// 1. It will not work incrementally.
|
||||
// 2. It will not produce the same results on little-endian and big-endian
|
||||
// machines.
|
||||
|
||||
#include "MurmurHash2.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform-specific functions and macros
|
||||
|
||||
// Microsoft Visual Studio
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#define BIG_CONSTANT(x) (x)
|
||||
|
||||
// Other compilers
|
||||
|
||||
#else // defined(_MSC_VER)
|
||||
|
||||
#define BIG_CONSTANT(x) (x##LLU)
|
||||
|
||||
#endif // !defined(_MSC_VER)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
|
||||
{
|
||||
// 'm' and 'r' are mixing constants generated offline.
|
||||
// They're not really 'magic', they just happen to work well.
|
||||
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
|
||||
// Initialize the hash to a 'random' value
|
||||
|
||||
uint32_t h = seed ^ len;
|
||||
|
||||
// Mix 4 bytes at a time into the hash
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h *= m;
|
||||
h ^= k;
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
case 2: h ^= data[1] << 8;
|
||||
case 1: h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
|
||||
// Do a few final mixes of the hash to ensure the last few
|
||||
// bytes are well-incorporated.
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHash2, 64-bit versions, by Austin Appleby
|
||||
|
||||
// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
|
||||
// and endian-ness issues if used across multiple platforms.
|
||||
|
||||
// 64-bit hash for 64-bit platforms
|
||||
|
||||
uint64_t MurmurHash64A ( const void * key, int len, uint64_t seed )
|
||||
{
|
||||
const uint64_t m = BIG_CONSTANT(0xc6a4a7935bd1e995);
|
||||
const int r = 47;
|
||||
|
||||
uint64_t h = seed ^ (len * m);
|
||||
|
||||
const uint64_t * data = (const uint64_t *)key;
|
||||
const uint64_t * end = data + (len/8);
|
||||
|
||||
while(data != end)
|
||||
{
|
||||
uint64_t k = *data++;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
}
|
||||
|
||||
const unsigned char * data2 = (const unsigned char*)data;
|
||||
|
||||
switch(len & 7)
|
||||
{
|
||||
case 7: h ^= uint64_t(data2[6]) << 48;
|
||||
case 6: h ^= uint64_t(data2[5]) << 40;
|
||||
case 5: h ^= uint64_t(data2[4]) << 32;
|
||||
case 4: h ^= uint64_t(data2[3]) << 24;
|
||||
case 3: h ^= uint64_t(data2[2]) << 16;
|
||||
case 2: h ^= uint64_t(data2[1]) << 8;
|
||||
case 1: h ^= uint64_t(data2[0]);
|
||||
h *= m;
|
||||
};
|
||||
|
||||
h ^= h >> r;
|
||||
h *= m;
|
||||
h ^= h >> r;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// 64-bit hash for 32-bit platforms
|
||||
|
||||
uint64_t MurmurHash64B ( const void * key, int len, uint64_t seed )
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
|
||||
uint32_t h1 = uint32_t(seed) ^ len;
|
||||
uint32_t h2 = uint32_t(seed >> 32);
|
||||
|
||||
const uint32_t * data = (const uint32_t *)key;
|
||||
|
||||
while(len >= 8)
|
||||
{
|
||||
uint32_t k1 = *data++;
|
||||
k1 *= m; k1 ^= k1 >> r; k1 *= m;
|
||||
h1 *= m; h1 ^= k1;
|
||||
len -= 4;
|
||||
|
||||
uint32_t k2 = *data++;
|
||||
k2 *= m; k2 ^= k2 >> r; k2 *= m;
|
||||
h2 *= m; h2 ^= k2;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
if(len >= 4)
|
||||
{
|
||||
uint32_t k1 = *data++;
|
||||
k1 *= m; k1 ^= k1 >> r; k1 *= m;
|
||||
h1 *= m; h1 ^= k1;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h2 ^= ((unsigned char*)data)[2] << 16;
|
||||
case 2: h2 ^= ((unsigned char*)data)[1] << 8;
|
||||
case 1: h2 ^= ((unsigned char*)data)[0];
|
||||
h2 *= m;
|
||||
};
|
||||
|
||||
h1 ^= h2 >> 18; h1 *= m;
|
||||
h2 ^= h1 >> 22; h2 *= m;
|
||||
h1 ^= h2 >> 17; h1 *= m;
|
||||
h2 ^= h1 >> 19; h2 *= m;
|
||||
|
||||
uint64_t h = h1;
|
||||
|
||||
h = (h << 32) | h2;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHash2A, by Austin Appleby
|
||||
|
||||
// This is a variant of MurmurHash2 modified to use the Merkle-Damgard
|
||||
// construction. Bulk speed should be identical to Murmur2, small-key speed
|
||||
// will be 10%-20% slower due to the added overhead at the end of the hash.
|
||||
|
||||
// This variant fixes a minor issue where null keys were more likely to
|
||||
// collide with each other than expected, and also makes the function
|
||||
// more amenable to incremental implementations.
|
||||
|
||||
#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
|
||||
|
||||
uint32_t MurmurHash2A ( const void * key, int len, uint32_t seed )
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
uint32_t l = len;
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
|
||||
uint32_t h = seed;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
|
||||
mmix(h,k);
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
uint32_t t = 0;
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: t ^= data[2] << 16;
|
||||
case 2: t ^= data[1] << 8;
|
||||
case 1: t ^= data[0];
|
||||
};
|
||||
|
||||
mmix(h,t);
|
||||
mmix(h,l);
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CMurmurHash2A, by Austin Appleby
|
||||
|
||||
// This is a sample implementation of MurmurHash2A designed to work
|
||||
// incrementally.
|
||||
|
||||
// Usage -
|
||||
|
||||
// CMurmurHash2A hasher
|
||||
// hasher.Begin(seed);
|
||||
// hasher.Add(data1,size1);
|
||||
// hasher.Add(data2,size2);
|
||||
// ...
|
||||
// hasher.Add(dataN,sizeN);
|
||||
// uint32_t hash = hasher.End()
|
||||
|
||||
class CMurmurHash2A
|
||||
{
|
||||
public:
|
||||
|
||||
void Begin ( uint32_t seed = 0 )
|
||||
{
|
||||
m_hash = seed;
|
||||
m_tail = 0;
|
||||
m_count = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void Add ( const unsigned char * data, int len )
|
||||
{
|
||||
m_size += len;
|
||||
|
||||
MixTail(data,len);
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
|
||||
mmix(m_hash,k);
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
MixTail(data,len);
|
||||
}
|
||||
|
||||
uint32_t End ( void )
|
||||
{
|
||||
mmix(m_hash,m_tail);
|
||||
mmix(m_hash,m_size);
|
||||
|
||||
m_hash ^= m_hash >> 13;
|
||||
m_hash *= m;
|
||||
m_hash ^= m_hash >> 15;
|
||||
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static const uint32_t m = 0x5bd1e995;
|
||||
static const int r = 24;
|
||||
|
||||
void MixTail ( const unsigned char * & data, int & len )
|
||||
{
|
||||
while( len && ((len<4) || m_count) )
|
||||
{
|
||||
m_tail |= (*data++) << (m_count * 8);
|
||||
|
||||
m_count++;
|
||||
len--;
|
||||
|
||||
if(m_count == 4)
|
||||
{
|
||||
mmix(m_hash,m_tail);
|
||||
m_tail = 0;
|
||||
m_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t m_hash;
|
||||
uint32_t m_tail;
|
||||
uint32_t m_count;
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHashNeutral2, by Austin Appleby
|
||||
|
||||
// Same as MurmurHash2, but endian- and alignment-neutral.
|
||||
// Half the speed though, alas.
|
||||
|
||||
uint32_t MurmurHashNeutral2 ( const void * key, int len, uint32_t seed )
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
|
||||
uint32_t h = seed ^ len;
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k;
|
||||
|
||||
k = data[0];
|
||||
k |= data[1] << 8;
|
||||
k |= data[2] << 16;
|
||||
k |= data[3] << 24;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h *= m;
|
||||
h ^= k;
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
case 2: h ^= data[1] << 8;
|
||||
case 1: h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHashAligned2, by Austin Appleby
|
||||
|
||||
// Same algorithm as MurmurHash2, but only does aligned reads - should be safer
|
||||
// on certain platforms.
|
||||
|
||||
// Performance will be lower than MurmurHash2
|
||||
|
||||
#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
|
||||
|
||||
|
||||
uint32_t MurmurHashAligned2 ( const void * key, int len, uint32_t seed )
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
|
||||
uint32_t h = seed ^ len;
|
||||
|
||||
int align = (uint64_t)data & 3;
|
||||
|
||||
if(align && (len >= 4))
|
||||
{
|
||||
// Pre-load the temp registers
|
||||
|
||||
uint32_t t = 0, d = 0;
|
||||
|
||||
switch(align)
|
||||
{
|
||||
case 1: t |= data[2] << 16;
|
||||
case 2: t |= data[1] << 8;
|
||||
case 3: t |= data[0];
|
||||
}
|
||||
|
||||
t <<= (8 * align);
|
||||
|
||||
data += 4-align;
|
||||
len -= 4-align;
|
||||
|
||||
int sl = 8 * (4-align);
|
||||
int sr = 8 * align;
|
||||
|
||||
// Mix
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
d = *(uint32_t *)data;
|
||||
t = (t >> sr) | (d << sl);
|
||||
|
||||
uint32_t k = t;
|
||||
|
||||
MIX(h,k,m);
|
||||
|
||||
t = d;
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
// Handle leftover data in temp registers
|
||||
|
||||
d = 0;
|
||||
|
||||
if(len >= align)
|
||||
{
|
||||
switch(align)
|
||||
{
|
||||
case 3: d |= data[2] << 16;
|
||||
case 2: d |= data[1] << 8;
|
||||
case 1: d |= data[0];
|
||||
}
|
||||
|
||||
uint32_t k = (t >> sr) | (d << sl);
|
||||
MIX(h,k,m);
|
||||
|
||||
data += align;
|
||||
len -= align;
|
||||
|
||||
//----------
|
||||
// Handle tail bytes
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
case 2: h ^= data[1] << 8;
|
||||
case 1: h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(len)
|
||||
{
|
||||
case 3: d |= data[2] << 16;
|
||||
case 2: d |= data[1] << 8;
|
||||
case 1: d |= data[0];
|
||||
case 0: h ^= (t >> sr) | (d << sl);
|
||||
h *= m;
|
||||
}
|
||||
}
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t *)data;
|
||||
|
||||
MIX(h,k,m);
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
//----------
|
||||
// Handle tail bytes
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
case 2: h ^= data[1] << 8;
|
||||
case 1: h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Sultan Tarimo
|
||||
|
||||
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, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Reference in new issue
Block a user