class Origami::Array

Class representing an Array Object. Arrays contain a set of Object.

Attributes

names_cache[R]
strings_cache[R]
xref_cache[R]

Public Class Methods

new(data = [], parser = nil, hint_type: nil) click to toggle source

Creates a new PDF Array Object.

data

An array of objects.

Calls superclass method Origami::Object::new
# File lib/origami/array.rb, line 45
def initialize(data = [], parser = nil, hint_type: nil)
    raise TypeError, "Expected type Array, received #{data.class}." unless data.is_a?(::Array)
    super()

    @strings_cache = []
    @names_cache = []
    @xref_cache = {}

    data.each_with_index do |value, index|
        value = value.to_o

        if Origami::OPTIONS[:enable_type_guessing]
            index_type = hint_type.is_a?(::Array) ? hint_type[index % hint_type.size] : hint_type
            if index_type.is_a?(::Array) and not value.is_a?(Reference)
                index_type = index_type.find {|type| type < value.class }
            end

            if index_type.is_a?(Class) and index_type < value.class
                value = value.cast_to(index_type, parser)
            end

            if index_type and parser and Origami::OPTIONS[:enable_type_propagation]
                if value.is_a?(Reference)
                    parser.defer_type_cast(value, index_type)
                end
            end
        end

        # Cache object value for fast search.
        cache_value(value)

        self.push(value)
    end
end
of(klass, *klasses, length: nil) click to toggle source

Parameterized Array class with additional typing information. Example: Array.of(Integer)

# File lib/origami/array.rb, line 198
def self.of(klass, *klasses, length: nil)
    Class.new(self) do
        const_set('ARRAY_TYPE', (klasses.empty? and not klass.is_a?(::Array)) ? klass : [ klass ].concat(klasses))
        const_set('STATIC_LENGTH', length)

        def initialize(data = [], parser = nil)
            super(data, parser, hint_type: self.class.const_get('ARRAY_TYPE'))
        end

        def pre_build #:nodoc:
            do_type_check if Origami::OPTIONS[:enable_type_checking]

            super
        end

        def self.parse(stream, parser = nil)
            super(stream, parser, hint_type: const_get('ARRAY_TYPE'))
        end

        def do_type_check #:nodoc:
            static_length = self.class.const_get('STATIC_LENGTH')
            array_type = self.class.const_get('ARRAY_TYPE')

            if static_length and self.length != static_length
                STDERR.puts "Warning: object #{self.class.name} has unexpected length #{self.length} (should be #{static_length})"
            end

            self.each_with_index do |object, index|
                index_type = array_type.is_a?(::Array) ? array_type[index % array_type.size] : array_type

                begin
                    object_value = object.solve
                rescue InvalidReferenceError
                    STDERR.puts "Warning: in object #{self.class}, invalid reference at index #{index}"
                    next
                end

                unless object_value.is_a?(index_type)
                    STDERR.puts "Warning: object #{self.class.name || 'Array'} should be composed of #{index_type.name} at index #{index} (got #{object_value.type} instead)"
                end
            end
        end
    end
end
parse(stream, parser = nil) click to toggle source
Calls superclass method
# File lib/origami/array.rb, line 213
def self.parse(stream, parser = nil)
    super(stream, parser, hint_type: const_get('ARRAY_TYPE'))
end

Public Instance Methods

+(other) click to toggle source
# File lib/origami/array.rb, line 133
def +(other)
    a = Origami::Array.new(self.to_a + other.to_a)
    a.no, a.generation = @no, @generation

    a
end
<<(item) click to toggle source
Calls superclass method
# File lib/origami/array.rb, line 140
def <<(item)
    obj = item.to_o
    obj.parent = self unless obj.indirect?

    super(obj)
end
Also aliased as: push
[]=(key, val) click to toggle source
Calls superclass method
# File lib/origami/array.rb, line 148
def []=(key, val)
    key, val = key.to_o, val.to_o
    super(key.to_o, val.to_o)

    val.parent = self unless val.indirect?
end
cast_to(type, parser = nil) click to toggle source
Calls superclass method
# File lib/origami/array.rb, line 179
def cast_to(type, parser = nil)
    super(type)

    cast = type.new(self.copy, parser)
    cast.parent = self.parent
    cast.no, cast.generation = self.no, self.generation
    if self.indirect?
        cast.set_indirect(true)
        cast.set_document(self.document)
        cast.file_offset = self.file_offset # cast can replace self
    end

    cast
end
concat(*arys) click to toggle source
# File lib/origami/array.rb, line 155
def concat(*arys)
    arys.each do |ary|
        ary.each do |e|
            val = e.to_o
            val.parent = self unless val.indirect?

            self.push(val)
        end
    end
end
copy() click to toggle source
# File lib/origami/array.rb, line 166
def copy
    copy = self.class.new
    self.each do |obj|
        copy << obj.copy
    end

    copy.parent = @parent
    copy.no, copy.generation = @no, @generation
    copy.set_indirect(true) if self.indirect?
    copy.set_document(@document) if self.indirect?
    copy
end
pre_build() click to toggle source
Calls superclass method Origami::Object#pre_build
# File lib/origami/array.rb, line 80
def pre_build
    self.map!{|obj| obj.to_o}

    super
end
push(item)
Alias for: <<
to_a() click to toggle source

Converts self into a Ruby array.

Calls superclass method
# File lib/origami/array.rb, line 111
def to_a
    super.map(&:value)
end
Also aliased as: value
to_obfuscated_str() click to toggle source
Calls superclass method Origami::Object#to_obfuscated_str
# File lib/origami/obfuscation.rb, line 154
def to_obfuscated_str
    content = TOKENS.first + Obfuscator.junk_spaces
    self.each do |entry|
        content << entry.to_o.to_obfuscated_str + Obfuscator.junk_spaces
    end

    content << TOKENS.last

    super(content)
end
value()
Alias for: to_a

Private Instance Methods

cache_value(value) click to toggle source
# File lib/origami/array.rb, line 245
def cache_value(value)
    case value
    when String then @strings_cache.push(value)
    when Name then @names_cache.push(value)
    when Reference then
        (@xref_cache[value] ||= []).push(self)
    when Dictionary, Array
        @strings_cache.concat(value.strings_cache)
        @names_cache.concat(value.names_cache)
        @xref_cache.update(value.xref_cache) do |_ref, cache1, cache2|
            cache1.concat(cache2)
        end

        value.strings_cache.clear
        value.names_cache.clear
        value.xref_cache.clear
    end
end