Created
May 18, 2009 10:34
-
-
Save samleb/113413 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Object.extend(Object, (function() { | |
function hashCode(object) { | |
if (!(object && Object.isFunction(object.hashCode))) { | |
object = String(object); | |
} | |
return object.hashCode(); | |
} | |
return { | |
hashCode: hashCode | |
}; | |
})); | |
Object.extend(String.prototype, (function() { | |
var SEED = Number(new Date()), | |
M = 0x5bd1e995, | |
R = 24; | |
function hashCode() { | |
var length = this.length, | |
result = SEED ^ length; | |
for (var i = 0; i < length; i++) { | |
k = this.charCodeAt(i); | |
k *= M; | |
k ^= k >> R; | |
k *= M; | |
result *= M; | |
result ^= k; | |
} | |
return result; | |
} | |
return { | |
hashCode: hashCode | |
} | |
})()); | |
/* | |
A Hash whose keys can be any sort of object. | |
*/ | |
var ObjectHash = Class.create(Enumerable, (function() { | |
function initialize() { | |
this._buckets = { }; | |
} | |
function _each(iterator) { | |
for (var hashCode in this._buckets) { | |
this._buckets[hashCode]._each(iterator); | |
}; | |
} | |
function keys() { | |
return Object.values(this._buckets).pluck('key'); | |
} | |
function values() { | |
return Object.values(this._buckets).pluck('value'); | |
} | |
function index(value) { | |
var match = this.detect(function(pair) { | |
return pair.value === value; | |
}); | |
return match && match.key; | |
} | |
function update(object) { | |
if (!(object instanceof ObjectHash)) | |
object = $H(object); | |
return object.inject(this, function(self, pair) { | |
self.set(pair.key, pair.value); | |
return self; | |
}); | |
} | |
function merge(object) { | |
return this.clone().update(object); | |
} | |
function get(key) { | |
var pair = findPair(key); | |
return pair && pair.value; | |
} | |
function hasKey(key) { | |
return Boolean(findPair(key)); | |
} | |
function set(key, value) { | |
var hashCode = Object.hashCode(key), | |
pairs = this._buckets[hashCode] = this._buckets[hashCode] || [], | |
pair = pairs.detect(function(p) { return p.key === key; }); | |
if (pair) { | |
pair.value = pair[1] = value; | |
} else { | |
// Mimic array properties to be consistent with Hash enumeration | |
pairs.push({ key: key, value: value, 0: key, 1: value }); | |
} | |
return value; | |
} | |
function unset(key) { | |
var hashCode = Object.hashCode(key), | |
pairs = this._buckets[hashCode], | |
value = null; | |
pairs && pairs.removeIf(function(pair) { | |
if (pair.key === key) { | |
value = pair.value; | |
return true; | |
} | |
}); | |
return value; | |
} | |
function clone() { | |
return new ObjectHash().update(this); | |
} | |
function findPair(key) { | |
var pairs = this._buckets[Object.hashCode(key)]; | |
if (!pairs) return null; | |
return pairs.detect(function(pair) { | |
return pair.key === key; | |
}); | |
} | |
return { | |
initialize: initialize, | |
_each: _each, | |
keys: keys, | |
values: values, | |
index: index, | |
merge: merge, | |
update: update, | |
get: get, | |
hasKey: hasKey, | |
set: set, | |
unset: unset, | |
clone: clone | |
}; | |
})()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment