Class: PDF::Reader::ObjectHash
- Inherits:
-
Object
- Object
- PDF::Reader::ObjectHash
- Includes:
- Enumerable
- Defined in:
- lib/pdf/reader/object_hash.rb
Overview
Provides low level access to the objects in a PDF file via a hash-like object.
A PDF file can be viewed as a large hash map. It is a series of objects stored at precise byte offsets, and a table that maps object IDs to byte offsets. Given an object ID, looking up an object is an O(1) operation.
Each PDF object can be mapped to a ruby object, so by passing an object ID to the [] method, a ruby representation of that object will be retrieved.
The class behaves much like a standard Ruby hash, including the use of the Enumerable mixin. The key difference is no []= method - the hash is read only.
Basic Usage
h = PDF::Reader::ObjectHash.new("somefile.pdf")
h[1]
=> 3469
h[PDF::Reader::Reference.new(1,0)]
=> 3469
Instance Attribute Summary collapse
- #default ⇒ Object
- #pdf_version ⇒ Object readonly
- #sec_handler ⇒ Object readonly
- #trailer ⇒ Object readonly
Instance Method Summary collapse
-
#[](key) ⇒ Object
Access an object from the PDF.
-
#deref!(key) ⇒ Object
Recursively dereferences the object refered to be
key. -
#deref_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
- #deref_array!(key) ⇒ Object
-
#deref_array_of_numbers(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_hash(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
- #deref_hash!(key) ⇒ Object
-
#deref_integer(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_name(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_name_or_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_number(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_stream(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_stream_or_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#deref_string(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#each(&block) ⇒ Object
(also: #each_pair)
iterate over each key, value.
-
#each_key(&block) ⇒ Object
iterate over each key.
-
#each_value(&block) ⇒ Object
iterate over each value.
-
#empty? ⇒ Boolean
return true if there are no objects in this file.
- #encrypted? ⇒ Boolean
-
#fetch(key, local_default = nil) ⇒ Object
Access an object from the PDF.
-
#has_key?(check_key) ⇒ Boolean
(also: #include?, #key?, #member?, #value?)
return true if the specified key exists in the file.
-
#has_value?(value) ⇒ Boolean
return true if the specifiedvalue exists in the file.
-
#initialize(input, opts = {}) ⇒ ObjectHash
constructor
Creates a new ObjectHash object.
-
#keys ⇒ Object
return an array of all keys in the file.
-
#obj_type(ref) ⇒ Object
returns the type of object a ref points to.
-
#object(key) ⇒ Object
(also: #deref)
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it.
-
#page_references ⇒ Object
returns an array of PDF::Reader::References.
- #sec_handler? ⇒ Boolean
-
#size ⇒ Object
(also: #length)
return the number of objects in the file.
-
#stream?(ref) ⇒ Boolean
returns true if the supplied references points to an object with a stream.
-
#to_a ⇒ Object
return an array of arrays.
- #to_s ⇒ Object
-
#values ⇒ Object
return an array of all values in the file.
-
#values_at(*ids) ⇒ Object
return an array of all values from the specified keys.
Constructor Details
#initialize(input, opts = {}) ⇒ ObjectHash
Creates a new ObjectHash object. Input can be a string with a valid filename or an IO-like object.
Valid options:
:password - the user password to decrypt the source PDF
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/pdf/reader/object_hash.rb', line 63 def initialize(input, opts = {}) @io = extract_io_from(input) #: untyped @xref = PDF::Reader::XRef.new(@io) #: PDF::Reader::XRef[PDF::Reader::Reference] @pdf_version = read_version #: Float @trailer = @xref.trailer #: Hash[Symbol, untyped] @cache = opts[:cache] || PDF::Reader::ObjectCache.new #: PDF::Reader::ObjectCache @sec_handler = NullSecurityHandler.new #: securityHandler @sec_handler = SecurityHandlerFactory.build( deref(trailer[:Encrypt]), deref(trailer[:ID]), opts[:password] ) @page_references = nil #: Array[PDF::Reader::Reference | Hash[Symbol, untyped]]? @object_streams = nil #: Hash[PDF::Reader::Reference, PDF::Reader::ObjectStream]? end |
Instance Attribute Details
#default ⇒ Object
44 45 46 |
# File 'lib/pdf/reader/object_hash.rb', line 44 def default @default end |
#pdf_version ⇒ Object (readonly)
50 51 52 |
# File 'lib/pdf/reader/object_hash.rb', line 50 def pdf_version @pdf_version end |
#sec_handler ⇒ Object (readonly)
53 54 55 |
# File 'lib/pdf/reader/object_hash.rb', line 53 def sec_handler @sec_handler end |
#trailer ⇒ Object (readonly)
47 48 49 |
# File 'lib/pdf/reader/object_hash.rb', line 47 def trailer @trailer end |
Instance Method Details
#[](key) ⇒ Object
Access an object from the PDF. key can be an int or a PDF::Reader::Reference object.
If an int is used, the object with that ID and a generation number of 0 will be returned.
If a PDF::Reader::Reference object is used the exact ID and generation number can be specified.
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/pdf/reader/object_hash.rb', line 103 def [](key) return default if key.to_i <= 0 unless key.is_a?(PDF::Reader::Reference) key = PDF::Reader::Reference.new(key.to_i, 0) end @cache[key] ||= fetch_object(key) || fetch_object_stream(key) rescue InvalidObjectError return default end |
#deref!(key) ⇒ Object
Recursively dereferences the object refered to be key. If key is not
a PDF::Reader::Reference, the key is returned unchanged.
355 356 357 |
# File 'lib/pdf/reader/object_hash.rb', line 355 def deref!(key) deref_internal!(key, {}) end |
#deref_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return an Array or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting an Array and no other type will do.
132 133 134 135 136 137 138 139 140 |
# File 'lib/pdf/reader/object_hash.rb', line 132 def deref_array(key) obj = deref(key) return obj if obj.nil? obj.tap { |obj| raise MalformedPDFError, "expected object to be an Array or nil" if !obj.is_a?(Array) } end |
#deref_array!(key) ⇒ Object
360 361 362 363 364 365 366 |
# File 'lib/pdf/reader/object_hash.rb', line 360 def deref_array!(key) deref!(key).tap { |obj| if !obj.nil? && !obj.is_a?(Array) raise MalformedPDFError, "expected object (#{obj.inspect}) to be an Array or nil" end } end |
#deref_array_of_numbers(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return an Array of Numerics or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting an Array and no other type will do.
Some effort to cast array elements to a number is made for any non-numeric elements.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/pdf/reader/object_hash.rb', line 152 def deref_array_of_numbers(key) arr = deref(key) return arr if arr.nil? raise MalformedPDFError, "expected object to be an Array" unless arr.is_a?(Array) arr.map { |item| if item.is_a?(Numeric) item elsif item.respond_to?(:to_f) item.to_f elsif item.respond_to?(:to_i) item.to_i else raise MalformedPDFError, "expected object to be a number" end } end |
#deref_hash(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a Hash or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a Hash and no other type will do.
180 181 182 183 184 185 186 187 188 |
# File 'lib/pdf/reader/object_hash.rb', line 180 def deref_hash(key) obj = deref(key) return obj if obj.nil? obj.tap { |obj| raise MalformedPDFError, "expected object to be a Hash or nil" if !obj.is_a?(Hash) } end |
#deref_hash!(key) ⇒ Object
369 370 371 372 373 374 375 |
# File 'lib/pdf/reader/object_hash.rb', line 369 def deref_hash!(key) deref!(key).tap { |obj| if !obj.nil? && !obj.is_a?(Hash) raise MalformedPDFError, "expected object (#{obj.inspect}) to be a Hash or nil" end } end |
#deref_integer(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return an Integer or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting an Integer and no other type will do.
Some effort to cast to an int is made when the reference points to a non-integer.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/pdf/reader/object_hash.rb', line 225 def deref_integer(key) obj = deref(key) return obj if obj.nil? if !obj.is_a?(Integer) if obj.respond_to?(:to_i) obj = obj.to_i else raise MalformedPDFError, "expected object to be an Integer" end end obj end |
#deref_name(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a PDF name (Symbol) or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a PDF Name and no other type will do.
Some effort to cast to a symbol is made when the reference points to a non-symbol.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/pdf/reader/object_hash.rb', line 200 def deref_name(key) obj = deref(key) return obj if obj.nil? if !obj.is_a?(Symbol) if obj.respond_to?(:to_sym) obj = obj.to_sym else raise MalformedPDFError, "expected object to be a Name" end end obj end |
#deref_name_or_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a PDF Name (symbol), Array or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a Name or Array and no other type will do.
320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/pdf/reader/object_hash.rb', line 320 def deref_name_or_array(key) obj = deref(key) return obj if obj.nil? obj.tap { |obj| if !obj.is_a?(Symbol) && !obj.is_a?(Array) raise MalformedPDFError, "expected object to be an Array or Name" end } end |
#deref_number(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a Numeric or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a Number and no other type will do.
Some effort to cast to a number is made when the reference points to a non-number.
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/pdf/reader/object_hash.rb', line 250 def deref_number(key) obj = deref(key) return obj if obj.nil? if !obj.is_a?(Numeric) if obj.respond_to?(:to_f) obj = obj.to_f elsif obj.respond_to?(:to_i) obj.to_i else raise MalformedPDFError, "expected object to be a number" end end obj end |
#deref_stream(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a PDF::Reader::Stream or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a stream and no other type will do.
276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/pdf/reader/object_hash.rb', line 276 def deref_stream(key) obj = deref(key) return obj if obj.nil? obj.tap { |obj| if !obj.is_a?(PDF::Reader::Stream) raise MalformedPDFError, "expected object to be a Stream or nil" end } end |
#deref_stream_or_array(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a PDF::Reader::Stream, Array or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a stream or Array and no other type will do.
339 340 341 342 343 344 345 346 347 348 349 |
# File 'lib/pdf/reader/object_hash.rb', line 339 def deref_stream_or_array(key) obj = deref(key) return obj if obj.nil? obj.tap { |obj| if !obj.is_a?(PDF::Reader::Stream) && !obj.is_a?(Array) raise MalformedPDFError, "expected object to be an Array or Stream" end } end |
#deref_string(key) ⇒ Object
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
Guaranteed to only return a String or nil. If the dereference results in any other type then a MalformedPDFError exception will raise. Useful when expecting a string and no other type will do.
Some effort to cast to a string is made when the reference points to a non-string.
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/pdf/reader/object_hash.rb', line 297 def deref_string(key) obj = deref(key) return obj if obj.nil? if !obj.is_a?(String) if obj.respond_to?(:to_s) obj = obj.to_s else raise MalformedPDFError, "expected object to be a string" end end obj end |
#each(&block) ⇒ Object Also known as: each_pair
iterate over each key, value. Just like a ruby hash.
@override(allow_incompatible: true)
405 406 407 408 409 |
# File 'lib/pdf/reader/object_hash.rb', line 405 def each(&block) @xref.each do |ref| yield ref, self[ref] end end |
#each_key(&block) ⇒ Object
iterate over each key. Just like a ruby hash.
415 416 417 418 419 |
# File 'lib/pdf/reader/object_hash.rb', line 415 def each_key(&block) each do |id, obj| yield id end end |
#each_value(&block) ⇒ Object
iterate over each value. Just like a ruby hash.
424 425 426 427 428 |
# File 'lib/pdf/reader/object_hash.rb', line 424 def each_value(&block) each do |id, obj| yield obj end end |
#empty? ⇒ Boolean
return true if there are no objects in this file
441 442 443 |
# File 'lib/pdf/reader/object_hash.rb', line 441 def empty? size == 0 ? true : false end |
#encrypted? ⇒ Boolean
533 534 535 |
# File 'lib/pdf/reader/object_hash.rb', line 533 def encrypted? trailer.has_key?(:Encrypt) end |
#fetch(key, local_default = nil) ⇒ Object
Access an object from the PDF. key can be an int or a PDF::Reader::Reference object.
If an int is used, the object with that ID and a generation number of 0 will be returned.
If a PDF::Reader::Reference object is used the exact ID and generation number can be specified.
local_default is the object that will be returned if the requested key doesn't exist.
390 391 392 393 394 395 396 397 398 399 |
# File 'lib/pdf/reader/object_hash.rb', line 390 def fetch(key, local_default = nil) obj = self[key] if obj return obj elsif local_default return local_default else raise IndexError, "#{key} is invalid" if key.to_i <= 0 end end |
#has_key?(check_key) ⇒ Boolean Also known as: include?, key?, member?, value?
return true if the specified key exists in the file. key can be an int or a PDF::Reader::Reference
449 450 451 452 453 454 455 456 457 458 459 |
# File 'lib/pdf/reader/object_hash.rb', line 449 def has_key?(check_key) # TODO update from O(n) to O(1) each_key do |key| if check_key.kind_of?(PDF::Reader::Reference) return true if check_key == key else return true if check_key.to_i == key.id end end return false end |
#has_value?(value) ⇒ Boolean
return true if the specifiedvalue exists in the file
467 468 469 470 471 472 473 |
# File 'lib/pdf/reader/object_hash.rb', line 467 def has_value?(value) # TODO update from O(n) to O(1) each_value do |obj| return true if obj == value end return false end |
#keys ⇒ Object
return an array of all keys in the file
484 485 486 487 488 |
# File 'lib/pdf/reader/object_hash.rb', line 484 def keys ret = [] each_key { |k| ret << k } ret end |
#obj_type(ref) ⇒ Object
returns the type of object a ref points to
81 82 83 84 85 |
# File 'lib/pdf/reader/object_hash.rb', line 81 def obj_type(ref) self[ref].class.to_s.to_sym rescue nil end |
#object(key) ⇒ Object Also known as: deref
If key is a PDF::Reader::Reference object, lookup the corresponding object in the PDF and return it. Otherwise return key untouched.
119 120 121 |
# File 'lib/pdf/reader/object_hash.rb', line 119 def object(key) key.is_a?(PDF::Reader::Reference) ? self[key] : key end |
#page_references ⇒ Object
returns an array of PDF::Reader::References. Each reference in the array points a Page object, one for each page in the PDF. The first reference is page 1, second reference is page 2, etc.
Useful for apps that want to extract data from specific pages.
524 525 526 527 528 529 530 |
# File 'lib/pdf/reader/object_hash.rb', line 524 def page_references root = fetch(trailer[:Root]) @page_references ||= begin pages_root = deref_hash(root[:Pages]) || {} get_page_objects(pages_root) end end |
#sec_handler? ⇒ Boolean
538 539 540 |
# File 'lib/pdf/reader/object_hash.rb', line 538 def sec_handler? !!sec_handler end |
#size ⇒ Object Also known as: length
return the number of objects in the file. An object with multiple generations is counted once.
433 434 435 |
# File 'lib/pdf/reader/object_hash.rb', line 433 def size xref.size end |
#stream?(ref) ⇒ Boolean
returns true if the supplied references points to an object with a stream
89 90 91 |
# File 'lib/pdf/reader/object_hash.rb', line 89 def stream?(ref) self.has_key?(ref) && self[ref].is_a?(PDF::Reader::Stream) end |
#to_a ⇒ Object
return an array of arrays. Each sub array contains a key/value pair.
509 510 511 512 513 514 515 |
# File 'lib/pdf/reader/object_hash.rb', line 509 def to_a ret = [] each do |id, obj| ret << [id, obj] end ret end |
#to_s ⇒ Object
477 478 479 |
# File 'lib/pdf/reader/object_hash.rb', line 477 def to_s "<PDF::Reader::ObjectHash size: #{self.size}>" end |
#values ⇒ Object
return an array of all values in the file
493 494 495 496 497 |
# File 'lib/pdf/reader/object_hash.rb', line 493 def values ret = [] each_value { |v| ret << v } ret end |
#values_at(*ids) ⇒ Object
return an array of all values from the specified keys
502 503 504 |
# File 'lib/pdf/reader/object_hash.rb', line 502 def values_at(*ids) ids.map { |id| self[id] } end |