Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial checkin

  • Loading branch information...
commit e8d5593b273f3e8289cb61186dd9d5f06ff8b912 0 parents
@skirwan authored
Showing with 195 additions and 0 deletions.
  1. +95 −0 JSLRU.js
  2. +4 −0 README.markdown
  3. +96 −0 index.html
95 JSLRU.js
@@ -0,0 +1,95 @@
+var LRUCache = (function(){
+ return function(cacheSize){
+ if ( typeof(cacheSize) != "number" ) cacheSize = 10;
+
+ var content = {};
+ var accessedKeys = [];
+ var accessCounter = 0;
+
+ function findIndexForAccessTime(accessTime) {
+ var low = 0;
+ var high = accessedKeys.length;
+ var mid;
+
+ while ( low <= high ) {
+ mid = Math.floor( ( low + high ) / 2 );
+ if ( accessTime < accessedKeys[mid].accessTime ) {
+ low = mid + 1;
+ } else if ( accessTime > accessedKeys[mid].accessTime ) {
+ high = mid - 1;
+ } else {
+ break;
+ }
+ }
+
+ if ( accessTime != accessedKeys[mid].accessTime ) {
+ throw "LRUCache accessedKeys didn't contain entry for access time " + entry + ".";
+ }
+
+ return mid;
+ }
+
+ return {
+ get : function(key) {
+ var entry = content[key];
+
+ if ( ! entry ) return null;
+
+ accessedKeys.splice(findIndexForAccessTime(entry.accessTime),1);
+
+ entry.accessTime = accessCounter ++;
+ accessedKeys.unshift( {
+ accessTime: entry.accessTime,
+ key: key
+ } );
+
+ return entry.value;
+ },
+
+ set : function(key, value) {
+ var existing = content[key];
+
+ if ( existing ) {
+
+ accessedKeys.splice(findIndexForAccessTime(existing.accessTime),1);
+
+ existing.accessTime = accessCounter ++;
+ accessedKeys.unshift( {
+ accessTime: existing.accessTime,
+ key: key
+ } );
+
+ existing.value = value;
+ } else {
+ var newEntry = {
+ accessTime: accessCounter ++,
+ value: value
+ }
+
+ content[key] = newEntry;
+
+ accessedKeys.unshift( {
+ accessTime: newEntry.accessTime,
+ key: key
+ } );
+
+ var removed = accessedKeys.splice( cacheSize );
+
+ for ( var i = 0 ; i < removed.length ; i ++ ) {
+ delete content[removed[i].key];
+ }
+ }
+ },
+
+ dump : function() {
+ var dump = {};
+
+ for ( var prop in content ) {
+ dump[prop] = { value: content[prop].value, accessTime: content[prop].accessTime };
+ }
+
+ return dump;
+ }
+ }
+ }
+})()
4 README.markdown
@@ -0,0 +1,4 @@
+JSLRU
+======
+
+A simple least-recently-used cache written in JavaScript.
96 index.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>JSLRU Demo</title>
+ <style type="text/css" media="screen">
+ table {
+ border:1px solid #999;
+ width:400px;
+ }
+ table td {
+ text-align:center;
+ }
+ table th {
+ border-bottom:1px solid #999;
+ }
+ textarea {
+ width:100%;
+ height:4em;
+ }
+ </style>
+ <script type="text/javascript" src="JSLRU.js"></script>
+ <script type="text/javascript" charset="utf-8">
+ function printDump(c) {
+ var dumpData = c.dump();
+
+ document.write('<table><tr><th>Key</th><th>Value</th><th>Access Time</th></tr>');
+
+ for ( prop in dumpData ) {
+ document.write('<tr>');
+ document.write('<td>' + prop + '</td>');
+ document.write('<td>' + dumpData[prop].value + '</td>');
+ document.write('<td>' + dumpData[prop].accessTime + '</td>');
+ document.write('</tr>');
+ }
+
+ document.write('</table>');
+ }
+
+ function label(str) {
+ document.write('<p>'+str+'</p>');
+ }
+
+ function assert(f) {
+ document.write( '<p>Assertion:</p>');
+ document.write( '<p>' + f + '</p>');
+
+ var succeeded = false;
+ try {
+ succeeded = f();
+ } catch (err) {
+ document.write('<p>Assertion threw exception:</p>');
+ document.write('<textarea>' + err + '</textarea>');
+ }
+
+ if ( succeeded ) {
+ document.write( '<p>Succeeded.</p> ');
+ } else {
+ document.write( '<p>Failed.</p> ');
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <script type="text/javascript" charset="utf-8">
+ label('Creating empty cache, size 2')
+ var cache = new LRUCache( 2 );
+
+ printDump(cache);
+
+ label('Adding foo=1')
+ cache.set('foo',1);
+ printDump(cache);
+
+ label('Adding bar=2')
+ cache.set('bar',2);
+ printDump(cache);
+
+ label('Adding bag=3')
+ cache.set('bag',3);
+ printDump(cache);
+
+ label('Fetching bar (putting it in front)');
+ assert( function(){ return cache.get('bar') == 2; } );
+ printDump(cache);
+
+ label('Adding marklar=4 (pushing bag out)')
+ cache.set('marklar',4);
+ printDump(cache);
+
+ label('Updating bar=5 (putting it in front)')
+ cache.set('bar',5);
+ assert( function(){ return cache.get('bar') == 5; } );
+ printDump(cache);
+ </script>
+ </body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.