module.exports = function(size) {

return new LruCache(size)

}

function LruCache(size) {

this.capacity = size | 0
this.map = Object.create(null)
this.list = new DoublyLinkedList()

}

LruCache.prototype.get = function(key) {

var node = this.map[key]
if (node == null) return undefined
this.used(node)
return node.val

}

LruCache.prototype.set = function(key, val) {

var node = this.map[key]
if (node != null) {
  node.val = val
} else {
  if (!this.capacity) this.prune()
  if (!this.capacity) return false
  node = new DoublyLinkedNode(key, val)
  this.map[key] = node
  this.capacity--
}
this.used(node)
return true

}

LruCache.prototype.used = function(node) {

this.list.moveToFront(node)

}

LruCache.prototype.prune = function() {

var node = this.list.pop()
if (node != null) {
  delete this.map[node.key]
  this.capacity++
}

}

function DoublyLinkedList() {

this.firstNode = null
this.lastNode = null

}

DoublyLinkedList.prototype.moveToFront = function(node) {

if (this.firstNode == node) return

this.remove(node)

if (this.firstNode == null) {
  this.firstNode = node
  this.lastNode = node
  node.prev = null
  node.next = null
} else {
  node.prev = null
  node.next = this.firstNode
  node.next.prev = node
  this.firstNode = node
}

}

DoublyLinkedList.prototype.pop = function() {

var lastNode = this.lastNode
if (lastNode != null) {
  this.remove(lastNode)
}
return lastNode

}

DoublyLinkedList.prototype.remove = function(node) {

if (this.firstNode == node) {
  this.firstNode = node.next
} else if (node.prev != null) {
  node.prev.next = node.next
}
if (this.lastNode == node) {
  this.lastNode = node.prev
} else if (node.next != null) {
  node.next.prev = node.prev
}

}

function DoublyLinkedNode(key, val) {

this.key = key
this.val = val
this.prev = null
this.next = null

}