111 lines
2.2 KiB
Ruby
111 lines
2.2 KiB
Ruby
# coding: utf-8
|
|
# typed: true
|
|
# frozen_string_literal: true
|
|
|
|
require 'hashery/lru_hash'
|
|
|
|
class PDF::Reader
|
|
|
|
# A Hash-like object for caching commonly used objects from a PDF file.
|
|
#
|
|
# This is an internal class, no promises about a stable API.
|
|
#
|
|
class ObjectCache # nodoc
|
|
|
|
# These object types use little memory and are accessed a heap of times as
|
|
# part of random page access, so we'll cache the unmarshalled objects and
|
|
# avoid lots of repetitive (and expensive) tokenising
|
|
CACHEABLE_TYPES = [:Catalog, :Page, :Pages]
|
|
|
|
attr_reader :hits, :misses
|
|
|
|
def initialize(lru_size = 1000)
|
|
@objects = {}
|
|
@lru_cache = Hashery::LRUHash.new(lru_size.to_i)
|
|
@hits = 0
|
|
@misses = 0
|
|
end
|
|
|
|
def [](key)
|
|
update_stats(key)
|
|
@objects[key] || @lru_cache[key]
|
|
end
|
|
|
|
def []=(key, value)
|
|
if cacheable?(value)
|
|
@objects[key] = value
|
|
else
|
|
@lru_cache[key] = value
|
|
end
|
|
end
|
|
|
|
def fetch(key, local_default = nil)
|
|
update_stats(key)
|
|
@objects[key] || @lru_cache.fetch(key, local_default)
|
|
end
|
|
|
|
def each(&block)
|
|
@objects.each(&block)
|
|
@lru_cache.each(&block)
|
|
end
|
|
alias :each_pair :each
|
|
|
|
def each_key(&block)
|
|
@objects.each_key(&block)
|
|
@lru_cache.each_key(&block)
|
|
end
|
|
|
|
def each_value(&block)
|
|
@objects.each_value(&block)
|
|
@lru_cache.each_value(&block)
|
|
end
|
|
|
|
def size
|
|
@objects.size + @lru_cache.size
|
|
end
|
|
alias :length :size
|
|
|
|
def empty?
|
|
@objects.empty? && @lru_cache.empty?
|
|
end
|
|
|
|
def include?(key)
|
|
@objects.include?(key) || @lru_cache.include?(key)
|
|
end
|
|
alias :has_key? :include?
|
|
alias :key? :include?
|
|
alias :member? :include?
|
|
|
|
def has_value?(value)
|
|
@objects.has_value?(value) || @lru_cache.has_value?(value)
|
|
end
|
|
|
|
def to_s
|
|
"<PDF::Reader::ObjectCache size: #{self.size}>"
|
|
end
|
|
|
|
def keys
|
|
@objects.keys + @lru_cache.keys
|
|
end
|
|
|
|
def values
|
|
@objects.values + @lru_cache.values
|
|
end
|
|
|
|
private
|
|
|
|
def update_stats(key)
|
|
if has_key?(key)
|
|
@hits += 1
|
|
else
|
|
@misses += 1
|
|
end
|
|
end
|
|
|
|
def cacheable?(obj)
|
|
obj.is_a?(Hash) && CACHEABLE_TYPES.include?(obj[:Type])
|
|
end
|
|
|
|
end
|
|
end
|