brew vendor-gems: commit updates.
This commit is contained in:
		
							parent
							
								
									763bf6f699
								
							
						
					
					
						commit
						dbd96b86c1
					
				
							
								
								
									
										10
									
								
								Library/Homebrew/vendor/bundle/bundler/setup.rb
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								Library/Homebrew/vendor/bundle/bundler/setup.rb
									
									
									
									
										vendored
									
									
								
							@ -51,13 +51,13 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.19.2/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.1.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.1.4/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5823/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.5866/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.2.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/pry-0.13.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/rdiscount-2.2.0.1"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/rdiscount-2.2.0.2"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.2/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/regexp_parser-1.7.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rexml-3.2.4/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ronn-0.7.3/lib"
 | 
			
		||||
@ -76,7 +76,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.88.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.7.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.42.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.2.0/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5823-universal-darwin-19/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5823/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.5866-universal-darwin-19/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.5866/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
 | 
			
		||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.4.1/lib"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
# BinData -- Binary data manipulator.
 | 
			
		||||
# Copyright (c) 2007 - 2018 Dion Mendel.
 | 
			
		||||
 | 
			
		||||
require 'bindata/version'
 | 
			
		||||
require 'bindata/array'
 | 
			
		||||
require 'bindata/bits'
 | 
			
		||||
require 'bindata/buffer'
 | 
			
		||||
require 'bindata/choice'
 | 
			
		||||
require 'bindata/count_bytes_remaining'
 | 
			
		||||
require 'bindata/delayed_io'
 | 
			
		||||
require 'bindata/float'
 | 
			
		||||
require 'bindata/int'
 | 
			
		||||
require 'bindata/primitive'
 | 
			
		||||
require 'bindata/record'
 | 
			
		||||
require 'bindata/rest'
 | 
			
		||||
require 'bindata/skip'
 | 
			
		||||
require 'bindata/string'
 | 
			
		||||
require 'bindata/stringz'
 | 
			
		||||
require 'bindata/struct'
 | 
			
		||||
require 'bindata/trace'
 | 
			
		||||
require 'bindata/uint8_array'
 | 
			
		||||
require 'bindata/virtual'
 | 
			
		||||
require 'bindata/alignment'
 | 
			
		||||
require 'bindata/warnings'
 | 
			
		||||
 | 
			
		||||
# = BinData
 | 
			
		||||
# 
 | 
			
		||||
# A declarative way to read and write structured binary data.
 | 
			
		||||
# 
 | 
			
		||||
# A full reference manual is available online at
 | 
			
		||||
# https://github.com/dmendel/bindata/wiki
 | 
			
		||||
#
 | 
			
		||||
# == License
 | 
			
		||||
#
 | 
			
		||||
# BinData is released under the same license as Ruby.
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2007 - 2018 Dion Mendel.
 | 
			
		||||
							
								
								
									
										79
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/alignment.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/alignment.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
require 'bindata/base_primitive'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Resets the stream alignment to the next byte.  This is
 | 
			
		||||
  # only useful when using bit-based primitives.
 | 
			
		||||
  #
 | 
			
		||||
  #    class MyRec < BinData::Record
 | 
			
		||||
  #      bit4 :a
 | 
			
		||||
  #      resume_byte_alignment
 | 
			
		||||
  #      bit4 :b
 | 
			
		||||
  #    end
 | 
			
		||||
  #
 | 
			
		||||
  #    MyRec.read("\x12\x34") #=> {"a" => 1, "b" => 3}
 | 
			
		||||
  #
 | 
			
		||||
  class ResumeByteAlignment < BinData::Base
 | 
			
		||||
    def clear?; true; end
 | 
			
		||||
    def assign(val); end
 | 
			
		||||
    def snapshot; nil; end
 | 
			
		||||
    def do_num_bytes; 0; end
 | 
			
		||||
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
      io.reset_read_bits
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io)
 | 
			
		||||
      io.flushbits
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # A monkey patch to force byte-aligned primitives to
 | 
			
		||||
  # become bit-aligned.  This allows them to be used at
 | 
			
		||||
  # non byte based boundaries.
 | 
			
		||||
  #
 | 
			
		||||
  #     class BitString < BinData::String
 | 
			
		||||
  #       bit_aligned
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  #     class MyRecord < BinData::Record
 | 
			
		||||
  #       bit4       :preamble
 | 
			
		||||
  #       bit_string :str, length: 2
 | 
			
		||||
  #     end
 | 
			
		||||
  #
 | 
			
		||||
  module BitAligned
 | 
			
		||||
    class BitAlignedIO
 | 
			
		||||
      def initialize(io)
 | 
			
		||||
        @io = io
 | 
			
		||||
      end
 | 
			
		||||
      def readbytes(n)
 | 
			
		||||
        n.times.inject("") do |bytes, _|
 | 
			
		||||
          bytes << @io.readbits(8, :big).chr
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def bit_aligned?
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      super(BitAlignedIO.new(io))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes
 | 
			
		||||
      super.to_f
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io)
 | 
			
		||||
      value_to_binary_string(_value).each_byte { |v| io.writebits(v, 8, :big) }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def BasePrimitive.bit_aligned
 | 
			
		||||
    include BitAligned
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def Primitive.bit_aligned
 | 
			
		||||
    fail "'bit_aligned' is not needed for BinData::Primitives"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										344
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,344 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # An Array is a list of data objects of the same type.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   data = "\x03\x04\x05\x06\x07\x08\x09"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Array.new(type: :int8, initial_length: 6)
 | 
			
		||||
  #   obj.read(data) #=> [3, 4, 5, 6, 7, 8]
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Array.new(type: :int8,
 | 
			
		||||
  #                            read_until: -> { index == 1 })
 | 
			
		||||
  #   obj.read(data) #=> [3, 4]
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Array.new(type: :int8,
 | 
			
		||||
  #                            read_until: -> { element >= 6 })
 | 
			
		||||
  #   obj.read(data) #=> [3, 4, 5, 6]
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Array.new(type: :int8,
 | 
			
		||||
  #           read_until: -> { array[index] + array[index - 1] == 13 })
 | 
			
		||||
  #   obj.read(data) #=> [3, 4, 5, 6, 7]
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Array.new(type: :int8, read_until: :eof)
 | 
			
		||||
  #   obj.read(data) #=> [3, 4, 5, 6, 7, 8, 9]
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:type</tt>::           The symbol representing the data type of the
 | 
			
		||||
  #                            array elements.  If the type is to have params
 | 
			
		||||
  #                            passed to it, then it should be provided as
 | 
			
		||||
  #                            <tt>[type_symbol, hash_params]</tt>.
 | 
			
		||||
  # <tt>:initial_length</tt>:: The initial length of the array.
 | 
			
		||||
  # <tt>:read_until</tt>::     While reading, elements are read until this
 | 
			
		||||
  #                            condition is true.  This is typically used to
 | 
			
		||||
  #                            read an array until a sentinel value is found.
 | 
			
		||||
  #                            The variables +index+, +element+ and +array+
 | 
			
		||||
  #                            are made available to any lambda assigned to
 | 
			
		||||
  #                            this parameter.  If the value of this parameter
 | 
			
		||||
  #                            is the symbol :eof, then the array will read
 | 
			
		||||
  #                            as much data from the stream as possible.
 | 
			
		||||
  #
 | 
			
		||||
  # Each data object in an array has the variable +index+ made available
 | 
			
		||||
  # to any lambda evaluated as a parameter of that data object.
 | 
			
		||||
  class Array < BinData::Base
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
    include Enumerable
 | 
			
		||||
 | 
			
		||||
    dsl_parser    :array
 | 
			
		||||
    arg_processor :array
 | 
			
		||||
 | 
			
		||||
    mandatory_parameter :type
 | 
			
		||||
    optional_parameters :initial_length, :read_until
 | 
			
		||||
    mutually_exclusive_parameters :initial_length, :read_until
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      @element_prototype = get_parameter(:type)
 | 
			
		||||
      if get_parameter(:read_until) == :eof
 | 
			
		||||
        extend ReadUntilEOFPlugin
 | 
			
		||||
      elsif has_parameter?(:read_until)
 | 
			
		||||
        extend ReadUntilPlugin
 | 
			
		||||
      elsif has_parameter?(:initial_length)
 | 
			
		||||
        extend InitialLengthPlugin
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @element_list = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear?
 | 
			
		||||
      @element_list.nil? || elements.all?(&:clear?)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(array)
 | 
			
		||||
      return if self.equal?(array)  # prevent self assignment
 | 
			
		||||
      raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil?
 | 
			
		||||
 | 
			
		||||
      @element_list = []
 | 
			
		||||
      concat(array)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      elements.collect(&:snapshot)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def find_index(obj)
 | 
			
		||||
      elements.index(obj)
 | 
			
		||||
    end
 | 
			
		||||
    alias index find_index
 | 
			
		||||
 | 
			
		||||
    # Returns the first index of +obj+ in self.
 | 
			
		||||
    #
 | 
			
		||||
    # Uses equal? for the comparator.
 | 
			
		||||
    def find_index_of(obj)
 | 
			
		||||
      elements.index { |el| el.equal?(obj) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def push(*args)
 | 
			
		||||
      insert(-1, *args)
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
    alias << push
 | 
			
		||||
 | 
			
		||||
    def unshift(*args)
 | 
			
		||||
      insert(0, *args)
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def concat(array)
 | 
			
		||||
      insert(-1, *array.to_ary)
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def insert(index, *objs)
 | 
			
		||||
      extend_array(index - 1)
 | 
			
		||||
      abs_index = (index >= 0) ? index : index + 1 + length
 | 
			
		||||
 | 
			
		||||
      # insert elements before...
 | 
			
		||||
      new_elements = objs.map { new_element }
 | 
			
		||||
      elements.insert(index, *new_elements)
 | 
			
		||||
 | 
			
		||||
      # ...assigning values
 | 
			
		||||
      objs.each_with_index do |obj, i|
 | 
			
		||||
        self[abs_index + i] = obj
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the element at +index+.
 | 
			
		||||
    def [](arg1, arg2 = nil)
 | 
			
		||||
      if arg1.respond_to?(:to_int) && arg2.nil?
 | 
			
		||||
        slice_index(arg1.to_int)
 | 
			
		||||
      elsif arg1.respond_to?(:to_int) && arg2.respond_to?(:to_int)
 | 
			
		||||
        slice_start_length(arg1.to_int, arg2.to_int)
 | 
			
		||||
      elsif arg1.is_a?(Range) && arg2.nil?
 | 
			
		||||
        slice_range(arg1)
 | 
			
		||||
      else
 | 
			
		||||
        raise TypeError, "can't convert #{arg1} into Integer" unless arg1.respond_to?(:to_int)
 | 
			
		||||
        raise TypeError, "can't convert #{arg2} into Integer" unless arg2.respond_to?(:to_int)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    alias slice []
 | 
			
		||||
 | 
			
		||||
    def slice_index(index)
 | 
			
		||||
      extend_array(index)
 | 
			
		||||
      at(index)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def slice_start_length(start, length)
 | 
			
		||||
      elements[start, length]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def slice_range(range)
 | 
			
		||||
      elements[range]
 | 
			
		||||
    end
 | 
			
		||||
    private :slice_index, :slice_start_length, :slice_range
 | 
			
		||||
 | 
			
		||||
    # Returns the element at +index+.  Unlike +slice+, if +index+ is out
 | 
			
		||||
    # of range the array will not be automatically extended.
 | 
			
		||||
    def at(index)
 | 
			
		||||
      elements[index]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets the element at +index+.
 | 
			
		||||
    def []=(index, value)
 | 
			
		||||
      extend_array(index)
 | 
			
		||||
      elements[index].assign(value)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the first element, or the first +n+ elements, of the array.
 | 
			
		||||
    # If the array is empty, the first form returns nil, and the second
 | 
			
		||||
    # form returns an empty array.
 | 
			
		||||
    def first(n = nil)
 | 
			
		||||
      if n.nil? && empty?
 | 
			
		||||
        # explicitly return nil as arrays grow automatically
 | 
			
		||||
        nil
 | 
			
		||||
      elsif n.nil?
 | 
			
		||||
        self[0]
 | 
			
		||||
      else
 | 
			
		||||
        self[0, n]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the last element, or the last +n+ elements, of the array.
 | 
			
		||||
    # If the array is empty, the first form returns nil, and the second
 | 
			
		||||
    # form returns an empty array.
 | 
			
		||||
    def last(n = nil)
 | 
			
		||||
      if n.nil?
 | 
			
		||||
        self[-1]
 | 
			
		||||
      else
 | 
			
		||||
        n = length if n > length
 | 
			
		||||
        self[-n, n]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def length
 | 
			
		||||
      elements.length
 | 
			
		||||
    end
 | 
			
		||||
    alias size length
 | 
			
		||||
 | 
			
		||||
    def empty?
 | 
			
		||||
      length.zero?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Allow this object to be used in array context.
 | 
			
		||||
    def to_ary
 | 
			
		||||
      collect { |el| el }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def each
 | 
			
		||||
      elements.each { |el| yield el }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def debug_name_of(child) #:nodoc:
 | 
			
		||||
      index = find_index_of(child)
 | 
			
		||||
      "#{debug_name}[#{index}]"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def offset_of(child) #:nodoc:
 | 
			
		||||
      index = find_index_of(child)
 | 
			
		||||
      sum = sum_num_bytes_below_index(index)
 | 
			
		||||
 | 
			
		||||
      child.bit_aligned? ? sum.floor : sum.ceil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io) #:nodoc:
 | 
			
		||||
      elements.each { |el| el.do_write(io) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      sum_num_bytes_for_all_elements
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def extend_array(max_index)
 | 
			
		||||
      max_length = max_index + 1
 | 
			
		||||
      while elements.length < max_length
 | 
			
		||||
        append_new_element
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def elements
 | 
			
		||||
      @element_list ||= []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def append_new_element
 | 
			
		||||
      element = new_element
 | 
			
		||||
      elements << element
 | 
			
		||||
      element
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def new_element
 | 
			
		||||
      @element_prototype.instantiate(nil, self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sum_num_bytes_for_all_elements
 | 
			
		||||
      sum_num_bytes_below_index(length)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sum_num_bytes_below_index(index)
 | 
			
		||||
      (0...index).inject(0) do |sum, i|
 | 
			
		||||
        nbytes = elements[i].do_num_bytes
 | 
			
		||||
 | 
			
		||||
        if nbytes.is_a?(Integer)
 | 
			
		||||
          sum.ceil + nbytes
 | 
			
		||||
        else
 | 
			
		||||
          sum + nbytes
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class ArrayArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params) #:nodoc:
 | 
			
		||||
      # ensure one of :initial_length and :read_until exists
 | 
			
		||||
      unless params.has_at_least_one_of?(:initial_length, :read_until)
 | 
			
		||||
        params[:initial_length] = 0
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      params.warn_replacement_parameter(:length, :initial_length)
 | 
			
		||||
      params.warn_replacement_parameter(:read_length, :initial_length)
 | 
			
		||||
      params.must_be_integer(:initial_length)
 | 
			
		||||
 | 
			
		||||
      params.merge!(obj_class.dsl_params)
 | 
			
		||||
      params.sanitize_object_prototype(:type)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :read_until parameter
 | 
			
		||||
  module ReadUntilPlugin
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
      loop do
 | 
			
		||||
        element = append_new_element
 | 
			
		||||
        element.do_read(io)
 | 
			
		||||
        variables = { index: self.length - 1, element: self.last, array: self }
 | 
			
		||||
        break if eval_parameter(:read_until, variables)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the read_until: :eof parameter
 | 
			
		||||
  module ReadUntilEOFPlugin
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
      loop do
 | 
			
		||||
        element = append_new_element
 | 
			
		||||
        begin
 | 
			
		||||
          element.do_read(io)
 | 
			
		||||
        rescue EOFError, IOError
 | 
			
		||||
          elements.pop
 | 
			
		||||
          break
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :initial_length parameter
 | 
			
		||||
  module InitialLengthPlugin
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
      elements.each { |el| el.do_read(io) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def elements
 | 
			
		||||
      if @element_list.nil?
 | 
			
		||||
        @element_list = []
 | 
			
		||||
        eval_parameter(:initial_length).times do
 | 
			
		||||
          @element_list << new_element
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @element_list
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										335
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/base.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/base.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,335 @@
 | 
			
		||||
require 'bindata/framework'
 | 
			
		||||
require 'bindata/io'
 | 
			
		||||
require 'bindata/lazy'
 | 
			
		||||
require 'bindata/name'
 | 
			
		||||
require 'bindata/params'
 | 
			
		||||
require 'bindata/registry'
 | 
			
		||||
require 'bindata/sanitize'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # This is the abstract base class for all data objects.
 | 
			
		||||
  class Base
 | 
			
		||||
    extend AcceptedParametersPlugin
 | 
			
		||||
    include Framework
 | 
			
		||||
    include RegisterNamePlugin
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
      # Instantiates this class and reads from +io+, returning the newly
 | 
			
		||||
      # created data object.  +args+ will be used when instantiating.
 | 
			
		||||
      def read(io, *args, &block)
 | 
			
		||||
        obj = self.new(*args)
 | 
			
		||||
        obj.read(io, &block)
 | 
			
		||||
        obj
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # The arg processor for this class.
 | 
			
		||||
      def arg_processor(name = nil)
 | 
			
		||||
        @arg_processor ||= nil
 | 
			
		||||
 | 
			
		||||
        if name
 | 
			
		||||
          @arg_processor = "#{name}_arg_processor".gsub(/(?:^|_)(.)/) { $1.upcase }.to_sym
 | 
			
		||||
        elsif @arg_processor.is_a? Symbol
 | 
			
		||||
          @arg_processor = BinData.const_get(@arg_processor).new
 | 
			
		||||
        elsif @arg_processor.nil?
 | 
			
		||||
          @arg_processor = superclass.arg_processor
 | 
			
		||||
        else
 | 
			
		||||
          @arg_processor
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # The name of this class as used by Records, Arrays etc.
 | 
			
		||||
      def bindata_name
 | 
			
		||||
        RegisteredClasses.underscore_name(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Call this method if this class is abstract and not to be used.
 | 
			
		||||
      def unregister_self
 | 
			
		||||
        RegisteredClasses.unregister(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Registers all subclasses of this class for use
 | 
			
		||||
      def register_subclasses #:nodoc:
 | 
			
		||||
        singleton_class.send(:undef_method, :inherited)
 | 
			
		||||
        define_singleton_method(:inherited) do |subclass|
 | 
			
		||||
          RegisteredClasses.register(subclass.name, subclass)
 | 
			
		||||
          register_subclasses
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private :unregister_self, :register_subclasses
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Register all subclasses of this class.
 | 
			
		||||
    register_subclasses
 | 
			
		||||
 | 
			
		||||
    # Set the initial arg processor.
 | 
			
		||||
    arg_processor :base
 | 
			
		||||
 | 
			
		||||
    # Creates a new data object.
 | 
			
		||||
    #
 | 
			
		||||
    # Args are optional, but if present, must be in the following order.
 | 
			
		||||
    #
 | 
			
		||||
    # +value+ is a value that is +assign+ed immediately after initialization.
 | 
			
		||||
    #
 | 
			
		||||
    # +parameters+ is a hash containing symbol keys.  Some parameters may
 | 
			
		||||
    # reference callable objects (methods or procs).
 | 
			
		||||
    #
 | 
			
		||||
    # +parent+ is the parent data object (e.g. struct, array, choice) this
 | 
			
		||||
    # object resides under.
 | 
			
		||||
    #
 | 
			
		||||
    def initialize(*args)
 | 
			
		||||
      value, @params, @parent = extract_args(args)
 | 
			
		||||
 | 
			
		||||
      initialize_shared_instance
 | 
			
		||||
      initialize_instance
 | 
			
		||||
      assign(value) if value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    attr_accessor :parent
 | 
			
		||||
    protected :parent=
 | 
			
		||||
 | 
			
		||||
    # Creates a new data object based on this instance.
 | 
			
		||||
    #
 | 
			
		||||
    # All parameters will be be duplicated.  Use this method
 | 
			
		||||
    # when creating multiple objects with the same parameters.
 | 
			
		||||
    def new(value = nil, parent = nil)
 | 
			
		||||
      obj = clone
 | 
			
		||||
      obj.parent = parent if parent
 | 
			
		||||
      obj.initialize_instance
 | 
			
		||||
      obj.assign(value) if value
 | 
			
		||||
 | 
			
		||||
      obj
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the result of evaluating the parameter identified by +key+.
 | 
			
		||||
    #
 | 
			
		||||
    # +overrides+ is an optional +parameters+ like hash that allow the
 | 
			
		||||
    # parameters given at object construction to be overridden.
 | 
			
		||||
    #
 | 
			
		||||
    # Returns nil if +key+ does not refer to any parameter.
 | 
			
		||||
    def eval_parameter(key, overrides = nil)
 | 
			
		||||
      value = get_parameter(key)
 | 
			
		||||
      if value.is_a?(Symbol) || value.respond_to?(:arity)
 | 
			
		||||
        lazy_evaluator.lazy_eval(value, overrides)
 | 
			
		||||
      else
 | 
			
		||||
        value
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a lazy evaluator for this object.
 | 
			
		||||
    def lazy_evaluator #:nodoc:
 | 
			
		||||
      @lazy ||= LazyEvaluator.new(self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the parameter referenced by +key+.
 | 
			
		||||
    # Use this method if you are sure the parameter is not to be evaluated.
 | 
			
		||||
    # You most likely want #eval_parameter.
 | 
			
		||||
    def get_parameter(key)
 | 
			
		||||
      @params[key]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns whether +key+ exists in the +parameters+ hash.
 | 
			
		||||
    def has_parameter?(key)
 | 
			
		||||
      @params.has_parameter?(key)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Resets the internal state to that of a newly created object.
 | 
			
		||||
    def clear
 | 
			
		||||
      initialize_instance
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Reads data into this data object.
 | 
			
		||||
    def read(io, &block)
 | 
			
		||||
      io = BinData::IO::Read.new(io) unless BinData::IO::Read === io
 | 
			
		||||
 | 
			
		||||
      start_read do
 | 
			
		||||
        clear
 | 
			
		||||
        do_read(io)
 | 
			
		||||
      end
 | 
			
		||||
      block.call(self) if block_given?
 | 
			
		||||
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Writes the value for this data object to +io+.
 | 
			
		||||
    def write(io, &block)
 | 
			
		||||
      io = BinData::IO::Write.new(io) unless BinData::IO::Write === io
 | 
			
		||||
 | 
			
		||||
      do_write(io)
 | 
			
		||||
      io.flush
 | 
			
		||||
 | 
			
		||||
      block.call(self) if block_given?
 | 
			
		||||
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the number of bytes it will take to write this data object.
 | 
			
		||||
    def num_bytes
 | 
			
		||||
      do_num_bytes.ceil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the string representation of this data object.
 | 
			
		||||
    def to_binary_s(&block)
 | 
			
		||||
      io = BinData::IO.create_string_io
 | 
			
		||||
      write(io, &block)
 | 
			
		||||
      io.string
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the hexadecimal string representation of this data object.
 | 
			
		||||
    def to_hex(&block)
 | 
			
		||||
      to_binary_s(&block).unpack('H*')[0]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return a human readable representation of this data object.
 | 
			
		||||
    def inspect
 | 
			
		||||
      snapshot.inspect
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return a string representing this data object.
 | 
			
		||||
    def to_s
 | 
			
		||||
      snapshot.to_s
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Work with Ruby's pretty-printer library.
 | 
			
		||||
    def pretty_print(pp) #:nodoc:
 | 
			
		||||
      pp.pp(snapshot)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Override and delegate =~ as it is defined in Object.
 | 
			
		||||
    def =~(other)
 | 
			
		||||
      snapshot =~ other
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a user friendly name of this object for debugging purposes.
 | 
			
		||||
    def debug_name
 | 
			
		||||
      if @parent
 | 
			
		||||
        @parent.debug_name_of(self)
 | 
			
		||||
      else
 | 
			
		||||
        "obj"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the offset (in bytes) of this object with respect to its most
 | 
			
		||||
    # distant ancestor.
 | 
			
		||||
    def abs_offset
 | 
			
		||||
      if @parent
 | 
			
		||||
        @parent.abs_offset + @parent.offset_of(self)
 | 
			
		||||
      else
 | 
			
		||||
        0
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the offset (in bytes) of this object with respect to its parent.
 | 
			
		||||
    def rel_offset
 | 
			
		||||
      if @parent
 | 
			
		||||
        @parent.offset_of(self)
 | 
			
		||||
      else
 | 
			
		||||
        0
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ==(other) #:nodoc:
 | 
			
		||||
      # double dispatch
 | 
			
		||||
      other == snapshot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # A version of +respond_to?+ used by the lazy evaluator.  It doesn't
 | 
			
		||||
    # reinvoke the evaluator so as to avoid infinite evaluation loops.
 | 
			
		||||
    def safe_respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      base_respond_to?(symbol, include_private)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alias base_respond_to? respond_to?
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def extract_args(args)
 | 
			
		||||
      self.class.arg_processor.extract_args(self.class, args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def start_read
 | 
			
		||||
      top_level_set(:in_read, true)
 | 
			
		||||
      yield
 | 
			
		||||
    ensure
 | 
			
		||||
      top_level_set(:in_read, false)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Is this object tree currently being read?  Used by BasePrimitive.
 | 
			
		||||
    def reading?
 | 
			
		||||
      top_level_get(:in_read)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def top_level_set(sym, value)
 | 
			
		||||
      top_level.instance_variable_set("@tl_#{sym}", value)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def top_level_get(sym)
 | 
			
		||||
      tl = top_level
 | 
			
		||||
      tl.instance_variable_defined?("@tl_#{sym}") &&
 | 
			
		||||
        tl.instance_variable_get("@tl_#{sym}")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def top_level
 | 
			
		||||
      if parent.nil?
 | 
			
		||||
        tl = self
 | 
			
		||||
      else
 | 
			
		||||
        tl = parent
 | 
			
		||||
        tl = tl.parent while tl.parent
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      tl
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def binary_string(str)
 | 
			
		||||
      str.to_s.dup.force_encoding(Encoding::BINARY)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # ArgProcessors process the arguments passed to BinData::Base.new into
 | 
			
		||||
  # the form required to initialise the BinData object.
 | 
			
		||||
  #
 | 
			
		||||
  # Any passed parameters are sanitized so the BinData object doesn't
 | 
			
		||||
  # need to perform error checking on the parameters.
 | 
			
		||||
  class BaseArgProcessor
 | 
			
		||||
    @@empty_hash = Hash.new.freeze
 | 
			
		||||
 | 
			
		||||
    # Takes the arguments passed to BinData::Base.new and
 | 
			
		||||
    # extracts [value, sanitized_parameters, parent].
 | 
			
		||||
    def extract_args(obj_class, obj_args)
 | 
			
		||||
      value, params, parent = separate_args(obj_class, obj_args)
 | 
			
		||||
      sanitized_params = SanitizedParameters.sanitize(params, obj_class)
 | 
			
		||||
 | 
			
		||||
      [value, sanitized_params, parent]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Separates the arguments passed to BinData::Base.new into
 | 
			
		||||
    # [value, parameters, parent].  Called by #extract_args.
 | 
			
		||||
    def separate_args(_obj_class, obj_args)
 | 
			
		||||
      args = obj_args.dup
 | 
			
		||||
      value = parameters = parent = nil
 | 
			
		||||
 | 
			
		||||
      if args.length > 1 && args.last.is_a?(BinData::Base)
 | 
			
		||||
        parent = args.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if args.length > 0 && args.last.is_a?(Hash)
 | 
			
		||||
        parameters = args.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if args.length > 0
 | 
			
		||||
        value = args.pop
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      parameters ||= @@empty_hash
 | 
			
		||||
 | 
			
		||||
      [value, parameters, parent]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Performs sanity checks on the given parameters.
 | 
			
		||||
    # This method converts the parameters to the form expected
 | 
			
		||||
    # by the data object.
 | 
			
		||||
    def sanitize_parameters!(obj_class, obj_params)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										248
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/base_primitive.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/base_primitive.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,248 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A BinData::BasePrimitive object is a container for a value that has a
 | 
			
		||||
  # particular binary representation.  A value corresponds to a primitive type
 | 
			
		||||
  # such as as integer, float or string.  Only one value can be contained by
 | 
			
		||||
  # this object.  This value can be read from or written to an IO stream.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Uint8.new(initial_value: 42)
 | 
			
		||||
  #   obj #=> 42
 | 
			
		||||
  #   obj.assign(5)
 | 
			
		||||
  #   obj #=> 5
 | 
			
		||||
  #   obj.clear
 | 
			
		||||
  #   obj #=> 42
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Uint8.new(value: 42)
 | 
			
		||||
  #   obj #=> 42
 | 
			
		||||
  #   obj.assign(5)
 | 
			
		||||
  #   obj #=> 42
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Uint8.new(assert: 3)
 | 
			
		||||
  #   obj.read("\005") #=> BinData::ValidityError: value is '5' but expected '3'
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Uint8.new(assert: -> { value < 5 })
 | 
			
		||||
  #   obj.read("\007") #=> BinData::ValidityError: value not as expected
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params include those for BinData::Base as well as:
 | 
			
		||||
  #
 | 
			
		||||
  # [<tt>:initial_value</tt>]  This is the initial value to use before one is
 | 
			
		||||
  #                            either #read or explicitly set with #value=.
 | 
			
		||||
  # [<tt>:value</tt>]          The object will always have this value.
 | 
			
		||||
  #                            Calls to #value= are ignored when
 | 
			
		||||
  #                            using this param.  While reading, #value
 | 
			
		||||
  #                            will return the value of the data read from the
 | 
			
		||||
  #                            IO, not the result of the <tt>:value</tt> param.
 | 
			
		||||
  # [<tt>:assert</tt>]         Raise an error unless the value read or assigned
 | 
			
		||||
  #                            meets this criteria.  The variable +value+ is
 | 
			
		||||
  #                            made available to any lambda assigned to this
 | 
			
		||||
  #                            parameter.  A boolean return indicates success
 | 
			
		||||
  #                            or failure.  Any other return is compared to
 | 
			
		||||
  #                            the value just read in.
 | 
			
		||||
  # [<tt>:asserted_value</tt>] Equivalent to <tt>:assert</tt> and <tt>:value</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  class BasePrimitive < BinData::Base
 | 
			
		||||
    unregister_self
 | 
			
		||||
 | 
			
		||||
    optional_parameters :initial_value, :value, :assert, :asserted_value
 | 
			
		||||
    mutually_exclusive_parameters :initial_value, :value
 | 
			
		||||
    mutually_exclusive_parameters :asserted_value, :value, :assert
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      extend InitialValuePlugin  if has_parameter?(:initial_value)
 | 
			
		||||
      extend ValuePlugin         if has_parameter?(:value)
 | 
			
		||||
      extend AssertPlugin        if has_parameter?(:assert)
 | 
			
		||||
      extend AssertedValuePlugin if has_parameter?(:asserted_value)
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @value = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear? #:nodoc:
 | 
			
		||||
      @value.nil?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      raise ArgumentError, "can't set a nil value for #{debug_name}" if val.nil?
 | 
			
		||||
 | 
			
		||||
      raw_val = val.respond_to?(:snapshot) ? val.snapshot : val
 | 
			
		||||
      @value =
 | 
			
		||||
        begin
 | 
			
		||||
          raw_val.dup
 | 
			
		||||
        rescue TypeError
 | 
			
		||||
          # can't dup Fixnums
 | 
			
		||||
          raw_val
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      _value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def value
 | 
			
		||||
      snapshot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def value=(val)
 | 
			
		||||
      assign(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      child = snapshot
 | 
			
		||||
      child.respond_to?(symbol, include_private) || super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      child = snapshot
 | 
			
		||||
      if child.respond_to?(symbol)
 | 
			
		||||
        self.class.class_eval \
 | 
			
		||||
          "def #{symbol}(*args, &block);" \
 | 
			
		||||
          "  snapshot.#{symbol}(*args, &block);" \
 | 
			
		||||
          "end"
 | 
			
		||||
        child.__send__(symbol, *args, &block)
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def <=>(other)
 | 
			
		||||
      snapshot <=> other
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def eql?(other)
 | 
			
		||||
      # double dispatch
 | 
			
		||||
      other.eql?(snapshot)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def hash
 | 
			
		||||
      snapshot.hash
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read(io) #:nodoc:
 | 
			
		||||
      @value = read_and_return_value(io)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io) #:nodoc:
 | 
			
		||||
      io.writebytes(value_to_binary_string(_value))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      value_to_binary_string(_value).length
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    # The unmodified value of this data object.  Note that #snapshot calls this
 | 
			
		||||
    # method.  This indirection is so that #snapshot can be overridden in
 | 
			
		||||
    # subclasses to modify the presentation value.
 | 
			
		||||
    def _value
 | 
			
		||||
      @value != nil ? @value : sensible_default
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Logic for the :value parameter
 | 
			
		||||
    module ValuePlugin
 | 
			
		||||
      def assign(val)
 | 
			
		||||
        # Ignored
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def _value
 | 
			
		||||
        reading? ? @value : eval_parameter(:value)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Logic for the :initial_value parameter
 | 
			
		||||
    module InitialValuePlugin
 | 
			
		||||
      def _value
 | 
			
		||||
        @value != nil ? @value : eval_parameter(:initial_value)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Logic for the :assert parameter
 | 
			
		||||
    module AssertPlugin
 | 
			
		||||
      def assign(val)
 | 
			
		||||
        super(val)
 | 
			
		||||
        assert!
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def do_read(io) #:nodoc:
 | 
			
		||||
        super(io)
 | 
			
		||||
        assert!
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def assert!
 | 
			
		||||
        current_value = snapshot
 | 
			
		||||
        expected = eval_parameter(:assert, value: current_value)
 | 
			
		||||
 | 
			
		||||
        msg =
 | 
			
		||||
          if !expected
 | 
			
		||||
            "value '#{current_value}' not as expected"
 | 
			
		||||
          elsif expected != true && current_value != expected
 | 
			
		||||
            "value is '#{current_value}' but expected '#{expected}'"
 | 
			
		||||
          else
 | 
			
		||||
            nil
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
        raise ValidityError, "#{msg} for #{debug_name}" if msg
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Logic for the :asserted_value parameter
 | 
			
		||||
    module AssertedValuePlugin
 | 
			
		||||
      def assign(val)
 | 
			
		||||
        assert_value(val)
 | 
			
		||||
        super(val)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def _value
 | 
			
		||||
        reading? ? @value : eval_parameter(:asserted_value)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def do_read(io) #:nodoc:
 | 
			
		||||
        super(io)
 | 
			
		||||
        assert!
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def assert!
 | 
			
		||||
        assert_value(snapshot)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def assert_value(current_value)
 | 
			
		||||
        expected = eval_parameter(:asserted_value, value: current_value)
 | 
			
		||||
        if current_value != expected
 | 
			
		||||
          raise ValidityError,
 | 
			
		||||
                "value is '#{current_value}' but " \
 | 
			
		||||
                "expected '#{expected}' for #{debug_name}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###########################################################################
 | 
			
		||||
    # To be implemented by subclasses
 | 
			
		||||
 | 
			
		||||
    # Return the string representation that +val+ will take when written.
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Read a number of bytes from +io+ and return the value they represent.
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return a sensible default for this data.
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # To be implemented by subclasses
 | 
			
		||||
    ###########################################################################
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/bits.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/bits.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,186 @@
 | 
			
		||||
require 'thread'
 | 
			
		||||
require 'bindata/base_primitive'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Defines a number of classes that contain a bit based integer.
 | 
			
		||||
  # The integer is defined by endian and number of bits.
 | 
			
		||||
 | 
			
		||||
  module BitField #:nodoc: all
 | 
			
		||||
    @@mutex = Mutex.new
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
      def define_class(name, nbits, endian, signed = :unsigned)
 | 
			
		||||
        @@mutex.synchronize do
 | 
			
		||||
          unless BinData.const_defined?(name)
 | 
			
		||||
            new_class = Class.new(BinData::BasePrimitive)
 | 
			
		||||
            BitField.define_methods(new_class, nbits, endian.to_sym, signed.to_sym)
 | 
			
		||||
            RegisteredClasses.register(name, new_class)
 | 
			
		||||
 | 
			
		||||
            BinData.const_set(name, new_class)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        BinData.const_get(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def define_methods(bit_class, nbits, endian, signed)
 | 
			
		||||
        bit_class.module_eval <<-END
 | 
			
		||||
          #{create_params_code(nbits)}
 | 
			
		||||
 | 
			
		||||
          def assign(val)
 | 
			
		||||
            #{create_nbits_code(nbits)}
 | 
			
		||||
            #{create_clamp_code(nbits, signed)}
 | 
			
		||||
            super(val)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def do_write(io)
 | 
			
		||||
            #{create_nbits_code(nbits)}
 | 
			
		||||
            val = _value
 | 
			
		||||
            #{create_int2uint_code(nbits, signed)}
 | 
			
		||||
            io.writebits(val, #{nbits}, :#{endian})
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def do_num_bytes
 | 
			
		||||
            #{create_nbits_code(nbits)}
 | 
			
		||||
            #{create_do_num_bytes_code(nbits)}
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def bit_aligned?
 | 
			
		||||
            true
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          #---------------
 | 
			
		||||
          private
 | 
			
		||||
 | 
			
		||||
          def read_and_return_value(io)
 | 
			
		||||
            #{create_nbits_code(nbits)}
 | 
			
		||||
            val = io.readbits(#{nbits}, :#{endian})
 | 
			
		||||
            #{create_uint2int_code(nbits, signed)}
 | 
			
		||||
            val
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def sensible_default
 | 
			
		||||
            0
 | 
			
		||||
          end
 | 
			
		||||
        END
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_params_code(nbits)
 | 
			
		||||
        if nbits == :nbits
 | 
			
		||||
          "mandatory_parameter :nbits"
 | 
			
		||||
        else
 | 
			
		||||
          ""
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_nbits_code(nbits)
 | 
			
		||||
        if nbits == :nbits
 | 
			
		||||
          "nbits = eval_parameter(:nbits)"
 | 
			
		||||
        else
 | 
			
		||||
          ""
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_do_num_bytes_code(nbits)
 | 
			
		||||
        if nbits == :nbits
 | 
			
		||||
          "nbits / 8.0"
 | 
			
		||||
        else
 | 
			
		||||
          nbits / 8.0
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_clamp_code(nbits, signed)
 | 
			
		||||
        if nbits == :nbits
 | 
			
		||||
          create_dynamic_clamp_code(signed)
 | 
			
		||||
        else
 | 
			
		||||
          create_fixed_clamp_code(nbits, signed)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_dynamic_clamp_code(signed)
 | 
			
		||||
        if signed == :signed
 | 
			
		||||
          max = "max = (1 << (nbits - 1)) - 1"
 | 
			
		||||
          min = "min = -(max + 1)"
 | 
			
		||||
        else
 | 
			
		||||
          max = "max = (1 << nbits) - 1"
 | 
			
		||||
          min = "min = 0"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        "#{max}; #{min}; val = (val < min) ? min : (val > max) ? max : val"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_fixed_clamp_code(nbits, signed)
 | 
			
		||||
        if nbits == 1 && signed == :signed
 | 
			
		||||
          raise "signed bitfield must have more than one bit"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if signed == :signed
 | 
			
		||||
          max = (1 << (nbits - 1)) - 1
 | 
			
		||||
          min = -(max + 1)
 | 
			
		||||
        else
 | 
			
		||||
          min = 0
 | 
			
		||||
          max = (1 << nbits) - 1
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        clamp = "(val < #{min}) ? #{min} : (val > #{max}) ? #{max} : val"
 | 
			
		||||
 | 
			
		||||
        if nbits == 1
 | 
			
		||||
          # allow single bits to be used as booleans
 | 
			
		||||
          clamp = "(val == true) ? 1 : (not val) ? 0 : #{clamp}"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        "val = #{clamp}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_int2uint_code(nbits, signed)
 | 
			
		||||
        if signed != :signed
 | 
			
		||||
          ""
 | 
			
		||||
        elsif nbits == :nbits
 | 
			
		||||
          "val &= (1 << nbits) - 1"
 | 
			
		||||
        else
 | 
			
		||||
          "val &= #{(1 << nbits) - 1}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_uint2int_code(nbits, signed)
 | 
			
		||||
        if signed != :signed
 | 
			
		||||
          ""
 | 
			
		||||
        elsif nbits == :nbits
 | 
			
		||||
          "val -= (1 << nbits) if (val >= (1 << (nbits - 1)))"
 | 
			
		||||
        else
 | 
			
		||||
          "val -= #{1 << nbits} if (val >= #{1 << (nbits - 1)})"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Create classes for dynamic bitfields
 | 
			
		||||
  {
 | 
			
		||||
    "Bit"    => :big,
 | 
			
		||||
    "BitLe"  => :little,
 | 
			
		||||
    "Sbit"   => [:big, :signed],
 | 
			
		||||
    "SbitLe" => [:little, :signed],
 | 
			
		||||
  }.each_pair { |name, args| BitField.define_class(name, :nbits, *args) }
 | 
			
		||||
 | 
			
		||||
  # Create classes on demand
 | 
			
		||||
  module BitFieldFactory
 | 
			
		||||
    def const_missing(name)
 | 
			
		||||
      mappings = {
 | 
			
		||||
        /^Bit(\d+)$/    => :big,
 | 
			
		||||
        /^Bit(\d+)le$/  => :little,
 | 
			
		||||
        /^Sbit(\d+)$/   => [:big, :signed],
 | 
			
		||||
        /^Sbit(\d+)le$/ => [:little, :signed]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      mappings.each_pair do |regex, args|
 | 
			
		||||
        if regex =~ name.to_s
 | 
			
		||||
          nbits = $1.to_i
 | 
			
		||||
          return BitField.define_class(name, nbits, *args)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      super(name)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  BinData.extend BitFieldFactory
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										117
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/buffer.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/buffer.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A Buffer is conceptually a substream within a data stream.  It has a
 | 
			
		||||
  # defined size and it will always read or write the exact number of bytes to
 | 
			
		||||
  # fill the buffer.  Short reads will skip over unused bytes and short writes
 | 
			
		||||
  # will pad the substream with "\0" bytes.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Buffer.new(length: 5, type: [:string, {value: "abc"}])
 | 
			
		||||
  #   obj.to_binary_s #=> "abc\000\000"
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  #   class MyBuffer < BinData::Buffer
 | 
			
		||||
  #     default_parameter length: 8
 | 
			
		||||
  #
 | 
			
		||||
  #     endian :little
 | 
			
		||||
  #
 | 
			
		||||
  #     uint16 :num1
 | 
			
		||||
  #     uint16 :num2
 | 
			
		||||
  #     # padding occurs here
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = MyBuffer.read("\001\000\002\000\000\000\000\000")
 | 
			
		||||
  #   obj.num1 #=> 1
 | 
			
		||||
  #   obj.num1 #=> 2
 | 
			
		||||
  #   obj.raw_num_bytes #=> 4
 | 
			
		||||
  #   obj.num_bytes #=> 8
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  #   class StringTable < BinData::Record
 | 
			
		||||
  #     endian :little
 | 
			
		||||
  #
 | 
			
		||||
  #     uint16 :table_size_in_bytes
 | 
			
		||||
  #     buffer :strings, length: :table_size_in_bytes do
 | 
			
		||||
  #       array read_until: :eof do
 | 
			
		||||
  #         uint8 :len
 | 
			
		||||
  #         string :str, length: :len
 | 
			
		||||
  #       end
 | 
			
		||||
  #     end
 | 
			
		||||
  #   end
 | 
			
		||||
  #     
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:length</tt>::   The number of bytes in the buffer.
 | 
			
		||||
  # <tt>:type</tt>::     The single type inside the buffer.  Use a struct if
 | 
			
		||||
  #                      multiple fields are required.
 | 
			
		||||
  class Buffer < BinData::Base
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
 | 
			
		||||
    dsl_parser    :buffer
 | 
			
		||||
    arg_processor :buffer
 | 
			
		||||
 | 
			
		||||
    mandatory_parameters :length, :type
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @type = get_parameter(:type).instantiate(nil, self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # The number of bytes used, ignoring the padding imposed by the buffer.
 | 
			
		||||
    def raw_num_bytes
 | 
			
		||||
      @type.num_bytes
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear?
 | 
			
		||||
      @type.clear?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      @type.assign(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      @type.snapshot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      @type.respond_to?(symbol, include_private) || super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      @type.__send__(symbol, *args, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read(io) #:nodoc:
 | 
			
		||||
      io.with_buffer(eval_parameter(:length)) do
 | 
			
		||||
        @type.do_read(io)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io) #:nodoc:
 | 
			
		||||
      io.with_buffer(eval_parameter(:length)) do
 | 
			
		||||
        @type.do_write(io)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      eval_parameter(:length)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class BufferArgProcessor < BaseArgProcessor
 | 
			
		||||
    include MultiFieldArgSeparator
 | 
			
		||||
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      params.merge!(obj_class.dsl_params)
 | 
			
		||||
      params.must_be_integer(:length)
 | 
			
		||||
      params.sanitize_object_prototype(:type)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/choice.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/choice.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,186 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A Choice is a collection of data objects of which only one is active
 | 
			
		||||
  # at any particular time.  Method calls will be delegated to the active
 | 
			
		||||
  # choice.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   type1 = [:string, {value: "Type1"}]
 | 
			
		||||
  #   type2 = [:string, {value: "Type2"}]
 | 
			
		||||
  #
 | 
			
		||||
  #   choices = {5 => type1, 17 => type2}
 | 
			
		||||
  #   a = BinData::Choice.new(choices: choices, selection: 5)
 | 
			
		||||
  #   a # => "Type1"
 | 
			
		||||
  #
 | 
			
		||||
  #   choices = [ type1, type2 ]
 | 
			
		||||
  #   a = BinData::Choice.new(choices: choices, selection: 1)
 | 
			
		||||
  #   a # => "Type2"
 | 
			
		||||
  #
 | 
			
		||||
  #   choices = [ nil, nil, nil, type1, nil, type2 ]
 | 
			
		||||
  #   a = BinData::Choice.new(choices: choices, selection: 3)
 | 
			
		||||
  #   a # => "Type1"
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  #   Chooser = Struct.new(:choice)
 | 
			
		||||
  #   mychoice = Chooser.new
 | 
			
		||||
  #   mychoice.choice = 'big'
 | 
			
		||||
  #
 | 
			
		||||
  #   choices = {'big' => :uint16be, 'little' => :uint16le}
 | 
			
		||||
  #   a = BinData::Choice.new(choices: choices, copy_on_change: true,
 | 
			
		||||
  #                           selection: -> { mychoice.choice })
 | 
			
		||||
  #   a.assign(256)
 | 
			
		||||
  #   a.to_binary_s #=> "\001\000"
 | 
			
		||||
  #
 | 
			
		||||
  #   mychoice.choice = 'little'
 | 
			
		||||
  #   a.to_binary_s #=> "\000\001"
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:choices</tt>::        Either an array or a hash specifying the possible
 | 
			
		||||
  #                            data objects.  The format of the
 | 
			
		||||
  #                            array/hash.values is a list of symbols
 | 
			
		||||
  #                            representing the data object type.  If a choice
 | 
			
		||||
  #                            is to have params passed to it, then it should
 | 
			
		||||
  #                            be provided as [type_symbol, hash_params].  An
 | 
			
		||||
  #                            implementation constraint is that the hash may
 | 
			
		||||
  #                            not contain symbols as keys, with the exception
 | 
			
		||||
  #                            of :default.  :default is to be used when then
 | 
			
		||||
  #                            :selection does not exist in the :choices hash.
 | 
			
		||||
  # <tt>:selection</tt>::      An index/key into the :choices array/hash which
 | 
			
		||||
  #                            specifies the currently active choice.
 | 
			
		||||
  # <tt>:copy_on_change</tt>:: If set to true, copy the value of the previous
 | 
			
		||||
  #                            selection to the current selection whenever the
 | 
			
		||||
  #                            selection changes.  Default is false.
 | 
			
		||||
  class Choice < BinData::Base
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
 | 
			
		||||
    dsl_parser    :choice
 | 
			
		||||
    arg_processor :choice
 | 
			
		||||
 | 
			
		||||
    mandatory_parameters :choices, :selection
 | 
			
		||||
    optional_parameter   :copy_on_change
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      extend CopyOnChangePlugin if eval_parameter(:copy_on_change) == true
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @choices = {}
 | 
			
		||||
      @last_selection = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the current selection.
 | 
			
		||||
    def selection
 | 
			
		||||
      selection = eval_parameter(:selection)
 | 
			
		||||
      if selection.nil?
 | 
			
		||||
        raise IndexError, ":selection returned nil for #{debug_name}"
 | 
			
		||||
      end
 | 
			
		||||
      selection
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      current_choice.respond_to?(symbol, include_private) || super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      current_choice.__send__(symbol, *args, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    %w(clear? assign snapshot do_read do_write do_num_bytes).each do |m|
 | 
			
		||||
      module_eval <<-END
 | 
			
		||||
        def #{m}(*args)
 | 
			
		||||
          current_choice.#{m}(*args)
 | 
			
		||||
        end
 | 
			
		||||
      END
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def current_choice
 | 
			
		||||
      current_selection = selection
 | 
			
		||||
      @choices[current_selection] ||= instantiate_choice(current_selection)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def instantiate_choice(selection)
 | 
			
		||||
      prototype = get_parameter(:choices)[selection]
 | 
			
		||||
      if prototype.nil?
 | 
			
		||||
        raise IndexError, "selection '#{selection}' does not exist in :choices for #{debug_name}"
 | 
			
		||||
      end
 | 
			
		||||
      prototype.instantiate(nil, self)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class ChoiceArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params) #:nodoc:
 | 
			
		||||
      params.merge!(obj_class.dsl_params)
 | 
			
		||||
 | 
			
		||||
      params.sanitize_choices(:choices) do |choices|
 | 
			
		||||
        hash_choices = choices_as_hash(choices)
 | 
			
		||||
        ensure_valid_keys(hash_choices)
 | 
			
		||||
        hash_choices
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #-------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def choices_as_hash(choices)
 | 
			
		||||
      if choices.respond_to?(:to_ary)
 | 
			
		||||
        key_array_by_index(choices.to_ary)
 | 
			
		||||
      else
 | 
			
		||||
        choices
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def key_array_by_index(array)
 | 
			
		||||
      result = {}
 | 
			
		||||
      array.each_with_index do |el, i|
 | 
			
		||||
        result[i] = el unless el.nil?
 | 
			
		||||
      end
 | 
			
		||||
      result
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ensure_valid_keys(choices)
 | 
			
		||||
      if choices.key?(nil)
 | 
			
		||||
        raise ArgumentError, ":choices hash may not have nil key"
 | 
			
		||||
      end
 | 
			
		||||
      if choices.keys.detect { |key| key.is_a?(Symbol) && key != :default }
 | 
			
		||||
        raise ArgumentError, ":choices hash may not have symbols for keys"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :copy_on_change parameter
 | 
			
		||||
  module CopyOnChangePlugin
 | 
			
		||||
    def current_choice
 | 
			
		||||
      obj = super
 | 
			
		||||
      copy_previous_value(obj)
 | 
			
		||||
      obj
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def copy_previous_value(obj)
 | 
			
		||||
      current_selection = selection
 | 
			
		||||
      prev = get_previous_choice(current_selection)
 | 
			
		||||
      obj.assign(prev) unless prev.nil?
 | 
			
		||||
      remember_current_selection(current_selection)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def get_previous_choice(selection)
 | 
			
		||||
      if @last_selection && selection != @last_selection
 | 
			
		||||
        @choices[@last_selection]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def remember_current_selection(selection)
 | 
			
		||||
      @last_selection = selection
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Counts the number of bytes remaining in the input stream from the current
 | 
			
		||||
  # position to the end of the stream.  This only makes sense for seekable
 | 
			
		||||
  # streams.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   class A < BinData::Record
 | 
			
		||||
  #     count_bytes_remaining :bytes_remaining
 | 
			
		||||
  #     string :all_data, read_length: :bytes_remaining
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = A.read("abcdefghij")
 | 
			
		||||
  #   obj.all_data #=> "abcdefghij"
 | 
			
		||||
  #
 | 
			
		||||
  class CountBytesRemaining < BinData::BasePrimitive
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      io.num_bytes_remaining
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      0
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										190
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/delayed_io.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/delayed_io.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,190 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # BinData declarations are evaluated in a single pass.
 | 
			
		||||
  # However, some binary formats require multi pass processing.  A common
 | 
			
		||||
  # reason is seeking backwards in the input stream.
 | 
			
		||||
  #
 | 
			
		||||
  # DelayedIO supports multi pass processing.  It works by ignoring the normal
 | 
			
		||||
  # #read or #write calls.  The user must explicitly call the #read_now! or
 | 
			
		||||
  # #write_now! methods to process an additional pass.  This additional pass
 | 
			
		||||
  # must specify the abs_offset of the I/O operation.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::DelayedIO.new(read_abs_offset: 3, type: :uint16be)
 | 
			
		||||
  #   obj.read("\x00\x00\x00\x11\x12")
 | 
			
		||||
  #   obj #=> 0
 | 
			
		||||
  #
 | 
			
		||||
  #   obj.read_now!
 | 
			
		||||
  #   obj #=> 0x1112
 | 
			
		||||
  #
 | 
			
		||||
  #   - OR -
 | 
			
		||||
  #
 | 
			
		||||
  #   obj.read("\x00\x00\x00\x11\x12") { obj.read_now! } #=> 0x1122
 | 
			
		||||
  #
 | 
			
		||||
  #   obj.to_binary_s { obj.write_now! } #=> "\x00\x00\x00\x11\x12"
 | 
			
		||||
  #
 | 
			
		||||
  # You can use the +auto_call_delayed_io+ keyword to cause #read and #write to
 | 
			
		||||
  # automatically perform the extra passes.
 | 
			
		||||
  #
 | 
			
		||||
  #   class ReversePascalString < BinData::Record
 | 
			
		||||
  #     auto_call_delayed_io
 | 
			
		||||
  #
 | 
			
		||||
  #     delayed_io :str, read_abs_offset: 0 do
 | 
			
		||||
  #       string read_length: :len
 | 
			
		||||
  #     end
 | 
			
		||||
  #     count_bytes_remaining :total_size
 | 
			
		||||
  #     skip to_abs_offset: -> { total_size - 1 }
 | 
			
		||||
  #     uint8  :len, value: -> { str.length }
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   s = ReversePascalString.read("hello\x05")
 | 
			
		||||
  #   s.to_binary_s #=> "hello\x05"
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:read_abs_offset</tt>::   The abs_offset to start reading at.
 | 
			
		||||
  # <tt>:type</tt>::              The single type inside the delayed io.  Use
 | 
			
		||||
  #                               a struct if multiple fields are required.
 | 
			
		||||
  class DelayedIO < BinData::Base
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
 | 
			
		||||
    dsl_parser    :delayed_io
 | 
			
		||||
    arg_processor :delayed_io
 | 
			
		||||
 | 
			
		||||
    mandatory_parameters :read_abs_offset, :type
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @type       = get_parameter(:type).instantiate(nil, self)
 | 
			
		||||
      @abs_offset = nil
 | 
			
		||||
      @read_io    = nil
 | 
			
		||||
      @write_io   = nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear?
 | 
			
		||||
      @type.clear?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      @type.assign(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      @type.snapshot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def num_bytes
 | 
			
		||||
      @type.num_bytes
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      @type.respond_to?(symbol, include_private) || super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      @type.__send__(symbol, *args, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def abs_offset
 | 
			
		||||
      @abs_offset || eval_parameter(:read_abs_offset)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets the +abs_offset+ to use when writing this object.
 | 
			
		||||
    def abs_offset=(offset)
 | 
			
		||||
      @abs_offset = offset
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def rel_offset
 | 
			
		||||
      abs_offset
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read(io) #:nodoc:
 | 
			
		||||
      @read_io = io
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io) #:nodoc:
 | 
			
		||||
      @write_io = io
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # DelayedIO objects aren't read when #read is called.
 | 
			
		||||
    # The reading is delayed until this method is called.
 | 
			
		||||
    def read_now!
 | 
			
		||||
      raise IOError, "read from where?" unless @read_io
 | 
			
		||||
 | 
			
		||||
      @read_io.seekbytes(abs_offset - @read_io.offset)
 | 
			
		||||
      start_read do
 | 
			
		||||
        @type.do_read(@read_io)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # DelayedIO objects aren't written when #write is called.
 | 
			
		||||
    # The writing is delayed until this method is called.
 | 
			
		||||
    def write_now!
 | 
			
		||||
      raise IOError, "write to where?" unless @write_io
 | 
			
		||||
      @write_io.seekbytes(abs_offset - @write_io.offset)
 | 
			
		||||
      @type.do_write(@write_io)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class DelayedIoArgProcessor < BaseArgProcessor
 | 
			
		||||
    include MultiFieldArgSeparator
 | 
			
		||||
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      params.merge!(obj_class.dsl_params)
 | 
			
		||||
      params.must_be_integer(:read_abs_offset)
 | 
			
		||||
      params.sanitize_object_prototype(:type)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Add +auto_call_delayed_io+ keyword to BinData::Base.
 | 
			
		||||
  class Base
 | 
			
		||||
    class << self
 | 
			
		||||
      # The +auto_call_delayed_io+ keyword sets a data object tree to perform
 | 
			
		||||
      # multi pass I/O automatically.
 | 
			
		||||
      def auto_call_delayed_io
 | 
			
		||||
        return if DelayedIO.method_defined? :initialize_instance_without_record_io
 | 
			
		||||
 | 
			
		||||
        include AutoCallDelayedIO
 | 
			
		||||
        DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance)
 | 
			
		||||
        DelayedIO.send(:define_method, :initialize_instance) do
 | 
			
		||||
          if @parent && !defined? @delayed_io_recorded
 | 
			
		||||
            @delayed_io_recorded = true
 | 
			
		||||
            list = top_level_get(:delayed_ios)
 | 
			
		||||
            list << self if list
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          initialize_instance_without_record_io
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module AutoCallDelayedIO
 | 
			
		||||
      def initialize_shared_instance
 | 
			
		||||
        top_level_set(:delayed_ios, [])
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def read(io)
 | 
			
		||||
        super(io) { top_level_get(:delayed_ios).each(&:read_now!) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def write(io, *_)
 | 
			
		||||
        super(io) { top_level_get(:delayed_ios).each(&:write_now!) }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def num_bytes
 | 
			
		||||
        to_binary_s.size
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										484
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/dsl.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										484
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/dsl.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,484 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # Extracts args for Records and Buffers.
 | 
			
		||||
  #
 | 
			
		||||
  # Foo.new(bar: "baz) is ambiguous as to whether :bar is a value or parameter.
 | 
			
		||||
  #
 | 
			
		||||
  # BaseArgExtractor always assumes :bar is parameter.  This extractor correctly
 | 
			
		||||
  # identifies it as value or parameter.
 | 
			
		||||
  module MultiFieldArgSeparator
 | 
			
		||||
    def separate_args(obj_class, obj_args)
 | 
			
		||||
      value, parameters, parent = super(obj_class, obj_args)
 | 
			
		||||
 | 
			
		||||
      if parameters_is_value?(obj_class, value, parameters)
 | 
			
		||||
        value = parameters
 | 
			
		||||
        parameters = {}
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      [value, parameters, parent]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def parameters_is_value?(obj_class, value, parameters)
 | 
			
		||||
      if value.nil? && !parameters.empty?
 | 
			
		||||
        field_names_in_parameters?(obj_class, parameters)
 | 
			
		||||
      else
 | 
			
		||||
        false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def field_names_in_parameters?(obj_class, parameters)
 | 
			
		||||
      field_names = obj_class.fields.field_names
 | 
			
		||||
      param_keys = parameters.keys
 | 
			
		||||
 | 
			
		||||
      !(field_names & param_keys).empty?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # BinData classes that are part of the DSL must be extended by this.
 | 
			
		||||
  module DSLMixin
 | 
			
		||||
    def dsl_parser(parser_type = nil)
 | 
			
		||||
      @dsl_parser ||= begin
 | 
			
		||||
        parser_type ||= superclass.dsl_parser.parser_type
 | 
			
		||||
        DSLParser.new(self, parser_type)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      dsl_parser.__send__(symbol, *args, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Assert object is not an array or string.
 | 
			
		||||
    def to_ary; nil; end
 | 
			
		||||
    def to_str; nil; end
 | 
			
		||||
 | 
			
		||||
    # A DSLParser parses and accumulates field definitions of the form
 | 
			
		||||
    #
 | 
			
		||||
    #   type name, params
 | 
			
		||||
    #
 | 
			
		||||
    # where:
 | 
			
		||||
    #   * +type+ is the under_scored name of a registered type
 | 
			
		||||
    #   * +name+ is the (possible optional) name of the field
 | 
			
		||||
    #   * +params+ is a hash containing any parameters
 | 
			
		||||
    #
 | 
			
		||||
    class DSLParser
 | 
			
		||||
      def initialize(the_class, parser_type)
 | 
			
		||||
        raise "unknown parser type #{parser_type}" unless parser_abilities[parser_type]
 | 
			
		||||
 | 
			
		||||
        @the_class      = the_class
 | 
			
		||||
        @parser_type    = parser_type
 | 
			
		||||
        @validator      = DSLFieldValidator.new(the_class, self)
 | 
			
		||||
        @endian         = nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      attr_reader :parser_type
 | 
			
		||||
 | 
			
		||||
      def endian(endian = nil)
 | 
			
		||||
        if endian
 | 
			
		||||
          set_endian(endian)
 | 
			
		||||
        elsif @endian.nil?
 | 
			
		||||
          set_endian(parent_attribute(:endian))
 | 
			
		||||
        end
 | 
			
		||||
        @endian
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def search_prefix(*args)
 | 
			
		||||
        @search_prefix ||= parent_attribute(:search_prefix, []).dup
 | 
			
		||||
 | 
			
		||||
        prefix = args.collect(&:to_sym).compact
 | 
			
		||||
        unless prefix.empty?
 | 
			
		||||
          if fields?
 | 
			
		||||
            dsl_raise SyntaxError, "search_prefix must be called before defining fields"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          @search_prefix = prefix.concat(@search_prefix)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        @search_prefix
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def hide(*args)
 | 
			
		||||
        if option?(:hidden_fields)
 | 
			
		||||
          @hide ||= parent_attribute(:hide, []).dup
 | 
			
		||||
 | 
			
		||||
          hidden = args.collect(&:to_sym).compact
 | 
			
		||||
          @hide.concat(hidden)
 | 
			
		||||
 | 
			
		||||
          @hide
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def fields
 | 
			
		||||
        @fields ||= SanitizedFields.new(hints, parent_fields)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def dsl_params
 | 
			
		||||
        abilities = parser_abilities[@parser_type]
 | 
			
		||||
        send(abilities.at(0), abilities.at(1))
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def method_missing(*args, &block)
 | 
			
		||||
        ensure_hints
 | 
			
		||||
        parse_and_append_field(*args, &block)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #-------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def parser_abilities
 | 
			
		||||
        @abilities ||= {
 | 
			
		||||
          struct:     [:to_struct_params, :struct,      [:multiple_fields, :optional_fieldnames, :hidden_fields]],
 | 
			
		||||
          array:      [:to_object_params, :type,        [:multiple_fields, :optional_fieldnames]],
 | 
			
		||||
          buffer:     [:to_object_params, :type,        [:multiple_fields, :optional_fieldnames, :hidden_fields]],
 | 
			
		||||
          choice:     [:to_choice_params, :choices,     [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]],
 | 
			
		||||
          delayed_io: [:to_object_params, :type,        [:multiple_fields, :optional_fieldnames, :hidden_fields]],
 | 
			
		||||
          primitive:  [:to_struct_params, :struct,      [:multiple_fields, :optional_fieldnames]],
 | 
			
		||||
          skip:       [:to_object_params, :until_valid, [:multiple_fields, :optional_fieldnames]],
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def option?(opt)
 | 
			
		||||
        parser_abilities[@parser_type].at(2).include?(opt)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def ensure_hints
 | 
			
		||||
        endian
 | 
			
		||||
        search_prefix
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def hints
 | 
			
		||||
        { endian: endian, search_prefix: search_prefix }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def set_endian(endian)
 | 
			
		||||
        if endian
 | 
			
		||||
          if fields?
 | 
			
		||||
            dsl_raise SyntaxError, "endian must be called before defining fields"
 | 
			
		||||
          end
 | 
			
		||||
          if !valid_endian?(endian)
 | 
			
		||||
            dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if endian == :big_and_little
 | 
			
		||||
            DSLBigAndLittleEndianHandler.handle(@the_class)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          @endian = endian
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def valid_endian?(endian)
 | 
			
		||||
        [:big, :little, :big_and_little].include?(endian)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parent_fields
 | 
			
		||||
        parent_attribute(:fields)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def fields?
 | 
			
		||||
        defined?(@fields) && !@fields.empty?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parse_and_append_field(*args, &block)
 | 
			
		||||
        parser = DSLFieldParser.new(hints, *args, &block)
 | 
			
		||||
        begin
 | 
			
		||||
          @validator.validate_field(parser.name)
 | 
			
		||||
          append_field(parser.type, parser.name, parser.params)
 | 
			
		||||
        rescue Exception => err
 | 
			
		||||
          dsl_raise err.class, err.message
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def append_field(type, name, params)
 | 
			
		||||
        fields.add_field(type, name, params)
 | 
			
		||||
      rescue BinData::UnRegisteredTypeError => err
 | 
			
		||||
        raise TypeError, "unknown type '#{err.message}'"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parent_attribute(attr, default = nil)
 | 
			
		||||
        parent = @the_class.superclass
 | 
			
		||||
        parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil
 | 
			
		||||
        if parser && parser.respond_to?(attr)
 | 
			
		||||
          parser.send(attr)
 | 
			
		||||
        else
 | 
			
		||||
          default
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def dsl_raise(exception, msg)
 | 
			
		||||
        backtrace = caller
 | 
			
		||||
        backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
 | 
			
		||||
 | 
			
		||||
        raise exception, "#{msg} in #{@the_class}", backtrace
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_object_params(key)
 | 
			
		||||
        case fields.length
 | 
			
		||||
        when 0
 | 
			
		||||
          {}
 | 
			
		||||
        when 1
 | 
			
		||||
          {key => fields[0].prototype}
 | 
			
		||||
        else
 | 
			
		||||
          {key=> [:struct, to_struct_params]}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_choice_params(key)
 | 
			
		||||
        if fields.empty?
 | 
			
		||||
          {}
 | 
			
		||||
        elsif fields.all_field_names_blank?
 | 
			
		||||
          {key => fields.collect(&:prototype)}
 | 
			
		||||
        else
 | 
			
		||||
          choices = {}
 | 
			
		||||
          fields.each { |f| choices[f.name] = f.prototype }
 | 
			
		||||
          {key => choices}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def to_struct_params(*unused)
 | 
			
		||||
        result = {fields: fields}
 | 
			
		||||
        if !endian.nil?
 | 
			
		||||
          result[:endian] = endian
 | 
			
		||||
        end
 | 
			
		||||
        if !search_prefix.empty?
 | 
			
		||||
          result[:search_prefix] = search_prefix
 | 
			
		||||
        end
 | 
			
		||||
        if option?(:hidden_fields) && !hide.empty?
 | 
			
		||||
          result[:hide] = hide
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        result
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Handles the :big_and_little endian option.
 | 
			
		||||
    # This option creates two subclasses, each handling
 | 
			
		||||
    # :big or :little endian.
 | 
			
		||||
    class DSLBigAndLittleEndianHandler
 | 
			
		||||
      class << self
 | 
			
		||||
        def handle(bnl_class)
 | 
			
		||||
          make_class_abstract(bnl_class)
 | 
			
		||||
          create_subclasses_with_endian(bnl_class)
 | 
			
		||||
          override_new_in_class(bnl_class)
 | 
			
		||||
          delegate_field_creation(bnl_class)
 | 
			
		||||
          fixup_subclass_hierarchy(bnl_class)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def make_class_abstract(bnl_class)
 | 
			
		||||
          bnl_class.send(:unregister_self)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def create_subclasses_with_endian(bnl_class)
 | 
			
		||||
          instance_eval "class ::#{bnl_class}Be < ::#{bnl_class}; endian :big; end"
 | 
			
		||||
          instance_eval "class ::#{bnl_class}Le < ::#{bnl_class}; endian :little; end"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def override_new_in_class(bnl_class)
 | 
			
		||||
          endian_classes = {
 | 
			
		||||
            big:    class_with_endian(bnl_class, :big),
 | 
			
		||||
            little: class_with_endian(bnl_class, :little),
 | 
			
		||||
          }
 | 
			
		||||
          bnl_class.define_singleton_method(:new) do |*args|
 | 
			
		||||
            if self == bnl_class
 | 
			
		||||
              _, options, _ = arg_processor.separate_args(self, args)
 | 
			
		||||
              delegate = endian_classes[options[:endian]]
 | 
			
		||||
              return delegate.new(*args) if delegate
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            super(*args)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def delegate_field_creation(bnl_class)
 | 
			
		||||
          endian_classes = {
 | 
			
		||||
            big:    class_with_endian(bnl_class, :big),
 | 
			
		||||
            little: class_with_endian(bnl_class, :little),
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          parser = bnl_class.dsl_parser
 | 
			
		||||
          parser.define_singleton_method(:parse_and_append_field) do |*args, &block|
 | 
			
		||||
            endian_classes[:big].send(*args, &block)
 | 
			
		||||
            endian_classes[:little].send(*args, &block)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def fixup_subclass_hierarchy(bnl_class)
 | 
			
		||||
          parent = bnl_class.superclass
 | 
			
		||||
          if obj_attribute(parent, :endian) == :big_and_little
 | 
			
		||||
            be_subclass = class_with_endian(bnl_class, :big)
 | 
			
		||||
            be_parent   = class_with_endian(parent, :big)
 | 
			
		||||
            be_fields   = obj_attribute(be_parent, :fields)
 | 
			
		||||
 | 
			
		||||
            le_subclass = class_with_endian(bnl_class, :little)
 | 
			
		||||
            le_parent   = class_with_endian(parent, :little)
 | 
			
		||||
            le_fields   = obj_attribute(le_parent, :fields)
 | 
			
		||||
 | 
			
		||||
            be_subclass.dsl_parser.define_singleton_method(:parent_fields) do
 | 
			
		||||
              be_fields
 | 
			
		||||
            end
 | 
			
		||||
            le_subclass.dsl_parser.define_singleton_method(:parent_fields) do
 | 
			
		||||
              le_fields
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def class_with_endian(class_name, endian)
 | 
			
		||||
          hints = {
 | 
			
		||||
            endian: endian,
 | 
			
		||||
            search_prefix: class_name.dsl_parser.search_prefix,
 | 
			
		||||
          }
 | 
			
		||||
          RegisteredClasses.lookup(class_name, hints)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def obj_attribute(obj, attr)
 | 
			
		||||
          obj.dsl_parser.send(attr)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Extracts the details from a field declaration.
 | 
			
		||||
    class DSLFieldParser
 | 
			
		||||
      def initialize(hints, symbol, *args, &block)
 | 
			
		||||
        @hints  = hints
 | 
			
		||||
        @type   = symbol
 | 
			
		||||
        @name   = name_from_field_declaration(args)
 | 
			
		||||
        @params = params_from_field_declaration(args, &block)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      attr_reader :type, :name, :params
 | 
			
		||||
 | 
			
		||||
      def name_from_field_declaration(args)
 | 
			
		||||
        name, _ = args
 | 
			
		||||
        if name == "" || name.is_a?(Hash)
 | 
			
		||||
          nil
 | 
			
		||||
        else
 | 
			
		||||
          name
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def params_from_field_declaration(args, &block)
 | 
			
		||||
        params = params_from_args(args)
 | 
			
		||||
 | 
			
		||||
        if block_given?
 | 
			
		||||
          params.merge(params_from_block(&block))
 | 
			
		||||
        else
 | 
			
		||||
          params
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def params_from_args(args)
 | 
			
		||||
        name, params = args
 | 
			
		||||
        params = name if name.is_a?(Hash)
 | 
			
		||||
 | 
			
		||||
        params || {}
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def params_from_block(&block)
 | 
			
		||||
        bindata_classes = {
 | 
			
		||||
          array:      BinData::Array,
 | 
			
		||||
          buffer:     BinData::Buffer,
 | 
			
		||||
          choice:     BinData::Choice,
 | 
			
		||||
          delayed_io: BinData::DelayedIO,
 | 
			
		||||
          skip:       BinData::Skip,
 | 
			
		||||
          struct:     BinData::Struct,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if bindata_classes.include?(@type)
 | 
			
		||||
          parser = DSLParser.new(bindata_classes[@type], @type)
 | 
			
		||||
          parser.endian(@hints[:endian])
 | 
			
		||||
          parser.search_prefix(*@hints[:search_prefix])
 | 
			
		||||
          parser.instance_eval(&block)
 | 
			
		||||
 | 
			
		||||
          parser.dsl_params
 | 
			
		||||
        else
 | 
			
		||||
          {}
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Validates a field defined in a DSLMixin.
 | 
			
		||||
    class DSLFieldValidator
 | 
			
		||||
      def initialize(the_class, parser)
 | 
			
		||||
        @the_class = the_class
 | 
			
		||||
        @dsl_parser = parser
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def validate_field(name)
 | 
			
		||||
        if must_not_have_a_name_failed?(name)
 | 
			
		||||
          raise SyntaxError, "field must not have a name"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if all_or_none_names_failed?(name)
 | 
			
		||||
          raise SyntaxError, "fields must either all have names, or none must have names"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if must_have_a_name_failed?(name)
 | 
			
		||||
          raise SyntaxError, "field must have a name"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        ensure_valid_name(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def ensure_valid_name(name)
 | 
			
		||||
        if name && !option?(:fieldnames_are_values)
 | 
			
		||||
          if malformed_name?(name)
 | 
			
		||||
            raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if duplicate_name?(name)
 | 
			
		||||
            raise SyntaxError, "duplicate field '#{name}'"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if name_shadows_method?(name)
 | 
			
		||||
            raise NameError.new("", name), "field '#{name}' shadows an existing method"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if name_is_reserved?(name)
 | 
			
		||||
            raise NameError.new("", name), "field '#{name}' is a reserved name"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def must_not_have_a_name_failed?(name)
 | 
			
		||||
        option?(:no_fieldnames) && !name.nil?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def must_have_a_name_failed?(name)
 | 
			
		||||
        option?(:mandatory_fieldnames) && name.nil?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def all_or_none_names_failed?(name)
 | 
			
		||||
        if option?(:all_or_none_fieldnames) && !fields.empty?
 | 
			
		||||
          all_names_blank = fields.all_field_names_blank?
 | 
			
		||||
          no_names_blank = fields.no_field_names_blank?
 | 
			
		||||
 | 
			
		||||
          (!name.nil? && all_names_blank) || (name.nil? && no_names_blank)
 | 
			
		||||
        else
 | 
			
		||||
          false
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def malformed_name?(name)
 | 
			
		||||
        /^[a-z_]\w*$/ !~ name.to_s
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def duplicate_name?(name)
 | 
			
		||||
        fields.field_name?(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def name_shadows_method?(name)
 | 
			
		||||
        @the_class.method_defined?(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def name_is_reserved?(name)
 | 
			
		||||
        BinData::Struct::RESERVED.include?(name.to_sym)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def fields
 | 
			
		||||
        @dsl_parser.fields
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def option?(opt)
 | 
			
		||||
        @dsl_parser.send(:option?, opt)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										83
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/float.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/float.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
require 'bindata/base_primitive'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Defines a number of classes that contain a floating point number.
 | 
			
		||||
  # The float is defined by precision and endian.
 | 
			
		||||
 | 
			
		||||
  module FloatingPoint #:nodoc: all
 | 
			
		||||
    class << self
 | 
			
		||||
      PRECISION = {
 | 
			
		||||
        single: 4,
 | 
			
		||||
        double: 8,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      PACK_CODE = {
 | 
			
		||||
        [:single, :little] => 'e',
 | 
			
		||||
        [:single, :big]    => 'g',
 | 
			
		||||
        [:double, :little] => 'E',
 | 
			
		||||
        [:double, :big]    => 'G',
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      def define_methods(float_class, precision, endian)
 | 
			
		||||
        float_class.module_eval <<-END
 | 
			
		||||
          def do_num_bytes
 | 
			
		||||
            #{create_num_bytes_code(precision)}
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          #---------------
 | 
			
		||||
          private
 | 
			
		||||
 | 
			
		||||
          def sensible_default
 | 
			
		||||
            0.0
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def value_to_binary_string(val)
 | 
			
		||||
            #{create_to_binary_s_code(precision, endian)}
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def read_and_return_value(io)
 | 
			
		||||
            #{create_read_code(precision, endian)}
 | 
			
		||||
          end
 | 
			
		||||
        END
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_num_bytes_code(precision)
 | 
			
		||||
        PRECISION[precision]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_read_code(precision, endian)
 | 
			
		||||
        nbytes = PRECISION[precision]
 | 
			
		||||
        unpack = PACK_CODE[[precision, endian]]
 | 
			
		||||
 | 
			
		||||
        "io.readbytes(#{nbytes}).unpack('#{unpack}').at(0)"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_to_binary_s_code(precision, endian)
 | 
			
		||||
        pack = PACK_CODE[[precision, endian]]
 | 
			
		||||
 | 
			
		||||
        "[val].pack('#{pack}')"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # Single precision floating point number in little endian format
 | 
			
		||||
  class FloatLe < BinData::BasePrimitive
 | 
			
		||||
    FloatingPoint.define_methods(self, :single, :little)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Single precision floating point number in big endian format
 | 
			
		||||
  class FloatBe < BinData::BasePrimitive
 | 
			
		||||
    FloatingPoint.define_methods(self, :single, :big)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Double precision floating point number in little endian format
 | 
			
		||||
  class DoubleLe < BinData::BasePrimitive
 | 
			
		||||
    FloatingPoint.define_methods(self, :double, :little)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Double precision floating point number in big endian format
 | 
			
		||||
  class DoubleBe < BinData::BasePrimitive
 | 
			
		||||
    FloatingPoint.define_methods(self, :double, :big)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										75
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/framework.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/framework.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # Error raised when unexpected results occur when reading data from IO.
 | 
			
		||||
  class ValidityError < StandardError ; end
 | 
			
		||||
 | 
			
		||||
  # All methods provided by the framework are to be implemented or overridden 
 | 
			
		||||
  # by subclasses of BinData::Base.
 | 
			
		||||
  module Framework
 | 
			
		||||
    # Initializes the state of the object.  All instance variables that
 | 
			
		||||
    # are used by the object must be initialized here.
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Initialises state that is shared by objects with the same parameters.
 | 
			
		||||
    #
 | 
			
		||||
    # This should only be used when optimising for performance.  Instance
 | 
			
		||||
    # variables set here, and changes to the singleton class will be shared
 | 
			
		||||
    # between all objects that are initialized with the same parameters.
 | 
			
		||||
    # This method is called only once for a particular set of parameters.
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns true if the object has not been changed since creation.
 | 
			
		||||
    def clear?
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Assigns the value of +val+ to this data object.  Note that +val+ must
 | 
			
		||||
    # always be deep copied to ensure no aliasing problems can occur.
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a snapshot of this data object.
 | 
			
		||||
    def snapshot
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the debug name of +child+.  This only needs to be implemented
 | 
			
		||||
    # by objects that contain child objects.
 | 
			
		||||
    def debug_name_of(child) #:nodoc:
 | 
			
		||||
      debug_name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the offset of +child+.  This only needs to be implemented
 | 
			
		||||
    # by objects that contain child objects.
 | 
			
		||||
    def offset_of(child) #:nodoc:
 | 
			
		||||
      0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Is this object aligned on non-byte boundaries?
 | 
			
		||||
    def bit_aligned?
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Reads the data for this data object from +io+.
 | 
			
		||||
    def do_read(io) #:nodoc:
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Writes the value for this data to +io+.
 | 
			
		||||
    def do_write(io) #:nodoc:
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the number of bytes it will take to write this data.
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set visibility requirements of methods to implement
 | 
			
		||||
    public :clear?, :assign, :snapshot, :debug_name_of, :offset_of
 | 
			
		||||
    protected :initialize_instance, :initialize_shared_instance
 | 
			
		||||
    protected :do_read, :do_write, :do_num_bytes
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										212
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/int.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/int.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,212 @@
 | 
			
		||||
require 'thread'
 | 
			
		||||
require 'bindata/base_primitive'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Defines a number of classes that contain an integer.  The integer
 | 
			
		||||
  # is defined by endian, signedness and number of bytes.
 | 
			
		||||
 | 
			
		||||
  module Int #:nodoc: all
 | 
			
		||||
    @@mutex = Mutex.new
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
      def define_class(name, nbits, endian, signed)
 | 
			
		||||
        @@mutex.synchronize do
 | 
			
		||||
          unless BinData.const_defined?(name)
 | 
			
		||||
            new_class = Class.new(BinData::BasePrimitive)
 | 
			
		||||
            Int.define_methods(new_class, nbits, endian.to_sym, signed.to_sym)
 | 
			
		||||
            RegisteredClasses.register(name, new_class)
 | 
			
		||||
 | 
			
		||||
            BinData.const_set(name, new_class)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        BinData.const_get(name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def define_methods(int_class, nbits, endian, signed)
 | 
			
		||||
        raise "nbits must be divisible by 8" unless (nbits % 8).zero?
 | 
			
		||||
 | 
			
		||||
        int_class.module_eval <<-END
 | 
			
		||||
          def assign(val)
 | 
			
		||||
            #{create_clamp_code(nbits, signed)}
 | 
			
		||||
            super(val)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def do_num_bytes
 | 
			
		||||
            #{nbits / 8}
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          #---------------
 | 
			
		||||
          private
 | 
			
		||||
 | 
			
		||||
          def sensible_default
 | 
			
		||||
            0
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def value_to_binary_string(val)
 | 
			
		||||
            #{create_clamp_code(nbits, signed)}
 | 
			
		||||
            #{create_to_binary_s_code(nbits, endian, signed)}
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def read_and_return_value(io)
 | 
			
		||||
            #{create_read_code(nbits, endian, signed)}
 | 
			
		||||
          end
 | 
			
		||||
        END
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #-------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def create_clamp_code(nbits, signed)
 | 
			
		||||
        if signed == :signed
 | 
			
		||||
          max = (1 << (nbits - 1)) - 1
 | 
			
		||||
          min = -(max + 1)
 | 
			
		||||
        else
 | 
			
		||||
          max = (1 << nbits) - 1
 | 
			
		||||
          min = 0
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        "val = (val < #{min}) ? #{min} : (val > #{max}) ? #{max} : val"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_read_code(nbits, endian, signed)
 | 
			
		||||
        read_str = create_raw_read_code(nbits, endian, signed)
 | 
			
		||||
 | 
			
		||||
        if need_signed_conversion_code?(nbits, signed)
 | 
			
		||||
          "val = #{read_str} ; #{create_uint2int_code(nbits)}"
 | 
			
		||||
        else
 | 
			
		||||
          read_str
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_raw_read_code(nbits, endian, signed)
 | 
			
		||||
        # special case 8bit integers for speed
 | 
			
		||||
        if nbits == 8
 | 
			
		||||
          "io.readbytes(1).ord"
 | 
			
		||||
        else
 | 
			
		||||
          unpack_str   = create_read_unpack_code(nbits, endian, signed)
 | 
			
		||||
          assemble_str = create_read_assemble_code(nbits, endian, signed)
 | 
			
		||||
 | 
			
		||||
          "(#{unpack_str} ; #{assemble_str})"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_read_unpack_code(nbits, endian, signed)
 | 
			
		||||
        nbytes         = nbits / 8
 | 
			
		||||
        pack_directive = pack_directive(nbits, endian, signed)
 | 
			
		||||
 | 
			
		||||
        "ints = io.readbytes(#{nbytes}).unpack('#{pack_directive}')"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_read_assemble_code(nbits, endian, signed)
 | 
			
		||||
        nwords = nbits / bits_per_word(nbits)
 | 
			
		||||
 | 
			
		||||
        idx = (0...nwords).to_a
 | 
			
		||||
        idx.reverse! if endian == :big
 | 
			
		||||
 | 
			
		||||
        parts = (0...nwords).collect do |i|
 | 
			
		||||
                  "(ints.at(#{idx[i]}) << #{bits_per_word(nbits) * i})"
 | 
			
		||||
                end
 | 
			
		||||
        parts[0].sub!(/ << 0\b/, "")  # Remove " << 0" for optimisation
 | 
			
		||||
 | 
			
		||||
        parts.join(" + ")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_to_binary_s_code(nbits, endian, signed)
 | 
			
		||||
        # special case 8bit integers for speed
 | 
			
		||||
        return "(val & 0xff).chr" if nbits == 8
 | 
			
		||||
 | 
			
		||||
        pack_directive = pack_directive(nbits, endian, signed)
 | 
			
		||||
        words          = val_as_packed_words(nbits, endian, signed)
 | 
			
		||||
        pack_str       = "[#{words}].pack('#{pack_directive}')"
 | 
			
		||||
 | 
			
		||||
        if need_signed_conversion_code?(nbits, signed)
 | 
			
		||||
          "#{create_int2uint_code(nbits)} ; #{pack_str}"
 | 
			
		||||
        else
 | 
			
		||||
          pack_str
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def val_as_packed_words(nbits, endian, signed)
 | 
			
		||||
        nwords = nbits / bits_per_word(nbits)
 | 
			
		||||
        mask   = (1 << bits_per_word(nbits)) - 1
 | 
			
		||||
 | 
			
		||||
        vals = (0...nwords).collect { |i| "val >> #{bits_per_word(nbits) * i}" }
 | 
			
		||||
        vals[0].sub!(/ >> 0\b/, "")  # Remove " >> 0" for optimisation
 | 
			
		||||
        vals.reverse! if (endian == :big)
 | 
			
		||||
 | 
			
		||||
        vals = vals.collect { |val| "#{val} & #{mask}" }  # TODO: "& mask" is needed to work around jruby bug. Remove this line when fixed.
 | 
			
		||||
        vals.join(",")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_int2uint_code(nbits)
 | 
			
		||||
        "val &= #{(1 << nbits) - 1}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def create_uint2int_code(nbits)
 | 
			
		||||
        "(val >= #{1 << (nbits - 1)}) ? val - #{1 << nbits} : val"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def bits_per_word(nbits)
 | 
			
		||||
        (nbits % 64).zero? ? 64 :
 | 
			
		||||
        (nbits % 32).zero? ? 32 :
 | 
			
		||||
        (nbits % 16).zero? ? 16 :
 | 
			
		||||
                              8
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def pack_directive(nbits, endian, signed)
 | 
			
		||||
        nwords = nbits / bits_per_word(nbits)
 | 
			
		||||
 | 
			
		||||
        directives = { 8 => "C", 16 => "S", 32 => "L", 64 => "Q" }
 | 
			
		||||
 | 
			
		||||
        d = directives[bits_per_word(nbits)]
 | 
			
		||||
        d << ((endian == :big) ? ">" : "<") unless d == "C"
 | 
			
		||||
 | 
			
		||||
        if signed == :signed && directives.key?(nbits)
 | 
			
		||||
          (d * nwords).downcase
 | 
			
		||||
        else
 | 
			
		||||
          d * nwords
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def need_signed_conversion_code?(nbits, signed)
 | 
			
		||||
        signed == :signed && ![64, 32, 16].include?(nbits)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # Unsigned 1 byte integer.
 | 
			
		||||
  class Uint8 < BinData::BasePrimitive
 | 
			
		||||
    Int.define_methods(self, 8, :little, :unsigned)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Signed 1 byte integer.
 | 
			
		||||
  class Int8 < BinData::BasePrimitive
 | 
			
		||||
    Int.define_methods(self, 8, :little, :signed)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Create classes on demand
 | 
			
		||||
  module IntFactory
 | 
			
		||||
    def const_missing(name)
 | 
			
		||||
      mappings = {
 | 
			
		||||
        /^Uint(\d+)be$/ => [:big,    :unsigned],
 | 
			
		||||
        /^Uint(\d+)le$/ => [:little, :unsigned],
 | 
			
		||||
        /^Int(\d+)be$/  => [:big,    :signed],
 | 
			
		||||
        /^Int(\d+)le$/  => [:little, :signed],
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      mappings.each_pair do |regex, args|
 | 
			
		||||
        if regex =~ name.to_s
 | 
			
		||||
          nbits = $1.to_i
 | 
			
		||||
          if nbits > 0 && (nbits % 8).zero?
 | 
			
		||||
            return Int.define_class(name, nbits, *args)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  BinData.extend IntFactory
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										496
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/io.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										496
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/io.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,496 @@
 | 
			
		||||
require 'stringio'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A wrapper around an IO object.  The wrapper provides a consistent
 | 
			
		||||
  # interface for BinData objects to use when accessing the IO.
 | 
			
		||||
  module IO
 | 
			
		||||
 | 
			
		||||
    # Common operations for both Read and Write.
 | 
			
		||||
    module Common
 | 
			
		||||
      def initialize(io)
 | 
			
		||||
        if self.class === io
 | 
			
		||||
          raise ArgumentError, "io must not be a #{self.class}"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # wrap strings in a StringIO
 | 
			
		||||
        if io.respond_to?(:to_str)
 | 
			
		||||
          io = BinData::IO.create_string_io(io.to_str)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        @raw_io = io
 | 
			
		||||
        @buffer_end_points = nil
 | 
			
		||||
 | 
			
		||||
        extend seekable? ? SeekableStream : UnSeekableStream
 | 
			
		||||
        stream_init
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #-------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def seekable?
 | 
			
		||||
        @raw_io.pos
 | 
			
		||||
      rescue NoMethodError, Errno::ESPIPE, Errno::EPIPE, Errno::EINVAL
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def seek(n)
 | 
			
		||||
        seek_raw(buffer_limited_n(n))
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def buffer_limited_n(n)
 | 
			
		||||
        if @buffer_end_points
 | 
			
		||||
          if n.nil? || n > 0
 | 
			
		||||
            max = @buffer_end_points[1] - offset
 | 
			
		||||
            n = max if n.nil? || n > max
 | 
			
		||||
          else
 | 
			
		||||
            min = @buffer_end_points[0] - offset
 | 
			
		||||
            n = min if n < min
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        n
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def with_buffer_common(n)
 | 
			
		||||
        prev = @buffer_end_points
 | 
			
		||||
        if prev
 | 
			
		||||
          avail = prev[1] - offset
 | 
			
		||||
          n = avail if n > avail
 | 
			
		||||
        end
 | 
			
		||||
        @buffer_end_points = [offset, offset + n]
 | 
			
		||||
        begin
 | 
			
		||||
          yield(*@buffer_end_points)
 | 
			
		||||
        ensure
 | 
			
		||||
          @buffer_end_points = prev
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Use #seek and #pos on seekable streams
 | 
			
		||||
      module SeekableStream
 | 
			
		||||
        # The number of bytes remaining in the input stream.
 | 
			
		||||
        def num_bytes_remaining
 | 
			
		||||
          start_mark = @raw_io.pos
 | 
			
		||||
          @raw_io.seek(0, ::IO::SEEK_END)
 | 
			
		||||
          end_mark = @raw_io.pos
 | 
			
		||||
 | 
			
		||||
          if @buffer_end_points
 | 
			
		||||
            if @buffer_end_points[1] < end_mark
 | 
			
		||||
              end_mark = @buffer_end_points[1]
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          bytes_remaining = end_mark - start_mark
 | 
			
		||||
          @raw_io.seek(start_mark, ::IO::SEEK_SET)
 | 
			
		||||
 | 
			
		||||
          bytes_remaining
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # All io calls in +block+ are rolled back after this
 | 
			
		||||
        # method completes.
 | 
			
		||||
        def with_readahead
 | 
			
		||||
          mark = @raw_io.pos
 | 
			
		||||
          begin
 | 
			
		||||
            yield
 | 
			
		||||
          ensure
 | 
			
		||||
            @raw_io.seek(mark, ::IO::SEEK_SET)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        #-----------
 | 
			
		||||
        private
 | 
			
		||||
 | 
			
		||||
        def stream_init
 | 
			
		||||
          @initial_pos = @raw_io.pos
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def offset_raw
 | 
			
		||||
          @raw_io.pos - @initial_pos
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def seek_raw(n)
 | 
			
		||||
          @raw_io.seek(n, ::IO::SEEK_CUR)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def read_raw(n)
 | 
			
		||||
          @raw_io.read(n)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def write_raw(data)
 | 
			
		||||
          @raw_io.write(data)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Manually keep track of offset for unseekable streams.
 | 
			
		||||
      module UnSeekableStream
 | 
			
		||||
        def offset_raw
 | 
			
		||||
          @offset
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # The number of bytes remaining in the input stream.
 | 
			
		||||
        def num_bytes_remaining
 | 
			
		||||
          raise IOError, "stream is unseekable"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # All io calls in +block+ are rolled back after this
 | 
			
		||||
        # method completes.
 | 
			
		||||
        def with_readahead
 | 
			
		||||
          mark = @offset
 | 
			
		||||
          @read_data = ""
 | 
			
		||||
          @in_readahead = true
 | 
			
		||||
 | 
			
		||||
          class << self
 | 
			
		||||
            alias_method :read_raw_without_readahead, :read_raw
 | 
			
		||||
            alias_method :read_raw, :read_raw_with_readahead
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          begin
 | 
			
		||||
            yield
 | 
			
		||||
          ensure
 | 
			
		||||
            @offset = mark
 | 
			
		||||
            @in_readahead = false
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        #-----------
 | 
			
		||||
        private
 | 
			
		||||
 | 
			
		||||
        def stream_init
 | 
			
		||||
          @offset = 0
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def read_raw(n)
 | 
			
		||||
          data = @raw_io.read(n)
 | 
			
		||||
          @offset += data.size if data
 | 
			
		||||
          data
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def read_raw_with_readahead(n)
 | 
			
		||||
          data = ""
 | 
			
		||||
 | 
			
		||||
          unless @read_data.empty? || @in_readahead
 | 
			
		||||
            bytes_to_consume = [n, @read_data.length].min
 | 
			
		||||
            data << @read_data.slice!(0, bytes_to_consume)
 | 
			
		||||
            n -= bytes_to_consume
 | 
			
		||||
 | 
			
		||||
            if @read_data.empty?
 | 
			
		||||
              class << self
 | 
			
		||||
                alias_method :read_raw, :read_raw_without_readahead
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          raw_data = @raw_io.read(n)
 | 
			
		||||
          data << raw_data if raw_data
 | 
			
		||||
 | 
			
		||||
          if @in_readahead
 | 
			
		||||
            @read_data << data
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          @offset += data.size
 | 
			
		||||
 | 
			
		||||
          data
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def write_raw(data)
 | 
			
		||||
          @offset += data.size
 | 
			
		||||
          @raw_io.write(data)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def seek_raw(n)
 | 
			
		||||
          raise IOError, "stream is unseekable" if n < 0
 | 
			
		||||
 | 
			
		||||
          # NOTE: how do we seek on a writable stream?
 | 
			
		||||
 | 
			
		||||
          # skip over data in 8k blocks
 | 
			
		||||
          while n > 0
 | 
			
		||||
            bytes_to_read = [n, 8192].min
 | 
			
		||||
            read_raw(bytes_to_read)
 | 
			
		||||
            n -= bytes_to_read
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Creates a StringIO around +str+.
 | 
			
		||||
    def self.create_string_io(str = "")
 | 
			
		||||
      s = StringIO.new(str.dup.force_encoding(Encoding::BINARY))
 | 
			
		||||
      s.binmode
 | 
			
		||||
      s
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Create a new IO Read wrapper around +io+.  +io+ must provide #read,
 | 
			
		||||
    # #pos if reading the current stream position and #seek if setting the
 | 
			
		||||
    # current stream position.  If +io+ is a string it will be automatically
 | 
			
		||||
    # wrapped in an StringIO object.
 | 
			
		||||
    #
 | 
			
		||||
    # The IO can handle bitstreams in either big or little endian format.
 | 
			
		||||
    #
 | 
			
		||||
    #      M  byte1   L      M  byte2   L
 | 
			
		||||
    #      S 76543210 S      S fedcba98 S
 | 
			
		||||
    #      B          B      B          B
 | 
			
		||||
    #
 | 
			
		||||
    # In big endian format:
 | 
			
		||||
    #   readbits(6), readbits(5) #=> [765432, 10fed]
 | 
			
		||||
    #
 | 
			
		||||
    # In little endian format:
 | 
			
		||||
    #   readbits(6), readbits(5) #=> [543210, a9876]
 | 
			
		||||
    #
 | 
			
		||||
    class Read
 | 
			
		||||
      include Common
 | 
			
		||||
 | 
			
		||||
      def initialize(io)
 | 
			
		||||
        super(io)
 | 
			
		||||
 | 
			
		||||
        # bits when reading
 | 
			
		||||
        @rnbits  = 0
 | 
			
		||||
        @rval    = 0
 | 
			
		||||
        @rendian = nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Sets a buffer of +n+ bytes on the io stream.  Any reading or seeking
 | 
			
		||||
      # calls inside the +block+ will be contained within this buffer.
 | 
			
		||||
      def with_buffer(n)
 | 
			
		||||
        with_buffer_common(n) do
 | 
			
		||||
          yield
 | 
			
		||||
          read
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the current offset of the io stream.  Offset will be rounded
 | 
			
		||||
      # up when reading bitfields.
 | 
			
		||||
      def offset
 | 
			
		||||
        offset_raw
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Seek +n+ bytes from the current position in the io stream.
 | 
			
		||||
      def seekbytes(n)
 | 
			
		||||
        reset_read_bits
 | 
			
		||||
        seek(n)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Reads exactly +n+ bytes from +io+.
 | 
			
		||||
      #
 | 
			
		||||
      # If the data read is nil an EOFError is raised.
 | 
			
		||||
      #
 | 
			
		||||
      # If the data read is too short an IOError is raised.
 | 
			
		||||
      def readbytes(n)
 | 
			
		||||
        reset_read_bits
 | 
			
		||||
        read(n)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Reads all remaining bytes from the stream.
 | 
			
		||||
      def read_all_bytes
 | 
			
		||||
        reset_read_bits
 | 
			
		||||
        read
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Reads exactly +nbits+ bits from the stream. +endian+ specifies whether
 | 
			
		||||
      # the bits are stored in +:big+ or +:little+ endian format.
 | 
			
		||||
      def readbits(nbits, endian)
 | 
			
		||||
        if @rendian != endian
 | 
			
		||||
          # don't mix bits of differing endian
 | 
			
		||||
          reset_read_bits
 | 
			
		||||
          @rendian = endian
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if endian == :big
 | 
			
		||||
          read_big_endian_bits(nbits)
 | 
			
		||||
        else
 | 
			
		||||
          read_little_endian_bits(nbits)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Discards any read bits so the stream becomes aligned at the
 | 
			
		||||
      # next byte boundary.
 | 
			
		||||
      def reset_read_bits
 | 
			
		||||
        @rnbits = 0
 | 
			
		||||
        @rval   = 0
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #---------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def read(n = nil)
 | 
			
		||||
        str = read_raw(buffer_limited_n(n))
 | 
			
		||||
        if n
 | 
			
		||||
          raise EOFError, "End of file reached" if str.nil?
 | 
			
		||||
          raise IOError, "data truncated" if str.size < n
 | 
			
		||||
        end
 | 
			
		||||
        str
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def read_big_endian_bits(nbits)
 | 
			
		||||
        while @rnbits < nbits
 | 
			
		||||
          accumulate_big_endian_bits
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        val     = (@rval >> (@rnbits - nbits)) & mask(nbits)
 | 
			
		||||
        @rnbits -= nbits
 | 
			
		||||
        @rval   &= mask(@rnbits)
 | 
			
		||||
 | 
			
		||||
        val
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def accumulate_big_endian_bits
 | 
			
		||||
        byte = read(1).unpack('C').at(0) & 0xff
 | 
			
		||||
        @rval = (@rval << 8) | byte
 | 
			
		||||
        @rnbits += 8
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def read_little_endian_bits(nbits)
 | 
			
		||||
        while @rnbits < nbits
 | 
			
		||||
          accumulate_little_endian_bits
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        val     = @rval & mask(nbits)
 | 
			
		||||
        @rnbits -= nbits
 | 
			
		||||
        @rval   >>= nbits
 | 
			
		||||
 | 
			
		||||
        val
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def accumulate_little_endian_bits
 | 
			
		||||
        byte = read(1).unpack('C').at(0) & 0xff
 | 
			
		||||
        @rval = @rval | (byte << @rnbits)
 | 
			
		||||
        @rnbits += 8
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def mask(nbits)
 | 
			
		||||
        (1 << nbits) - 1
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Create a new IO Write wrapper around +io+.  +io+ must provide #write.
 | 
			
		||||
    # If +io+ is a string it will be automatically wrapped in an StringIO
 | 
			
		||||
    # object.
 | 
			
		||||
    #
 | 
			
		||||
    # The IO can handle bitstreams in either big or little endian format.
 | 
			
		||||
    #
 | 
			
		||||
    # See IO::Read for more information.
 | 
			
		||||
    class Write
 | 
			
		||||
      include Common
 | 
			
		||||
      def initialize(io)
 | 
			
		||||
        super(io)
 | 
			
		||||
 | 
			
		||||
        @wnbits  = 0
 | 
			
		||||
        @wval    = 0
 | 
			
		||||
        @wendian = nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Sets a buffer of +n+ bytes on the io stream.  Any writes inside the
 | 
			
		||||
      # +block+ will be contained within this buffer.  If less than +n+ bytes
 | 
			
		||||
      # are written inside the block, the remainder will be padded with '\0'
 | 
			
		||||
      # bytes.
 | 
			
		||||
      def with_buffer(n)
 | 
			
		||||
        with_buffer_common(n) do |_buf_start, buf_end|
 | 
			
		||||
          yield
 | 
			
		||||
          write("\0" * (buf_end - offset))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the current offset of the io stream.  Offset will be rounded
 | 
			
		||||
      # up when writing bitfields.
 | 
			
		||||
      def offset
 | 
			
		||||
        offset_raw + (@wnbits > 0 ? 1 : 0)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Seek +n+ bytes from the current position in the io stream.
 | 
			
		||||
      def seekbytes(n)
 | 
			
		||||
        flushbits
 | 
			
		||||
        seek(n)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Writes the given string of bytes to the io stream.
 | 
			
		||||
      def writebytes(str)
 | 
			
		||||
        flushbits
 | 
			
		||||
        write(str)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Writes +nbits+ bits from +val+ to the stream. +endian+ specifies whether
 | 
			
		||||
      # the bits are to be stored in +:big+ or +:little+ endian format.
 | 
			
		||||
      def writebits(val, nbits, endian)
 | 
			
		||||
        if @wendian != endian
 | 
			
		||||
          # don't mix bits of differing endian
 | 
			
		||||
          flushbits
 | 
			
		||||
          @wendian = endian
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        clamped_val = val & mask(nbits)
 | 
			
		||||
 | 
			
		||||
        if endian == :big
 | 
			
		||||
          write_big_endian_bits(clamped_val, nbits)
 | 
			
		||||
        else
 | 
			
		||||
          write_little_endian_bits(clamped_val, nbits)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # To be called after all +writebits+ have been applied.
 | 
			
		||||
      def flushbits
 | 
			
		||||
        raise "Internal state error nbits = #{@wnbits}" if @wnbits >= 8
 | 
			
		||||
 | 
			
		||||
        if @wnbits > 0
 | 
			
		||||
          writebits(0, 8 - @wnbits, @wendian)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      alias flush flushbits
 | 
			
		||||
 | 
			
		||||
      #---------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def write(data)
 | 
			
		||||
        n = buffer_limited_n(data.size)
 | 
			
		||||
        if n < data.size
 | 
			
		||||
          data = data[0, n]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        write_raw(data)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def write_big_endian_bits(val, nbits)
 | 
			
		||||
        while nbits > 0
 | 
			
		||||
          bits_req = 8 - @wnbits
 | 
			
		||||
          if nbits >= bits_req
 | 
			
		||||
            msb_bits = (val >> (nbits - bits_req)) & mask(bits_req)
 | 
			
		||||
            nbits -= bits_req
 | 
			
		||||
            val &= mask(nbits)
 | 
			
		||||
 | 
			
		||||
            @wval   = (@wval << bits_req) | msb_bits
 | 
			
		||||
            write(@wval.chr)
 | 
			
		||||
 | 
			
		||||
            @wval   = 0
 | 
			
		||||
            @wnbits = 0
 | 
			
		||||
          else
 | 
			
		||||
            @wval = (@wval << nbits) | val
 | 
			
		||||
            @wnbits += nbits
 | 
			
		||||
            nbits = 0
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def write_little_endian_bits(val, nbits)
 | 
			
		||||
        while nbits > 0
 | 
			
		||||
          bits_req = 8 - @wnbits
 | 
			
		||||
          if nbits >= bits_req
 | 
			
		||||
            lsb_bits = val & mask(bits_req)
 | 
			
		||||
            nbits -= bits_req
 | 
			
		||||
            val >>= bits_req
 | 
			
		||||
 | 
			
		||||
            @wval   = @wval | (lsb_bits << @wnbits)
 | 
			
		||||
            write(@wval.chr)
 | 
			
		||||
 | 
			
		||||
            @wval   = 0
 | 
			
		||||
            @wnbits = 0
 | 
			
		||||
          else
 | 
			
		||||
            @wval   = @wval | (val << @wnbits)
 | 
			
		||||
            @wnbits += nbits
 | 
			
		||||
            nbits = 0
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def mask(nbits)
 | 
			
		||||
        (1 << nbits) - 1
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										109
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/lazy.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/lazy.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # A LazyEvaluator is bound to a data object.  The evaluator will evaluate
 | 
			
		||||
  # lambdas in the context of this data object.  These lambdas
 | 
			
		||||
  # are those that are passed to data objects as parameters, e.g.:
 | 
			
		||||
  #
 | 
			
		||||
  #    BinData::String.new(value: -> { %w(a test message).join(" ") })
 | 
			
		||||
  #
 | 
			
		||||
  # As a shortcut, :foo is the equivalent of lambda { foo }.
 | 
			
		||||
  #
 | 
			
		||||
  # When evaluating lambdas, unknown methods are resolved in the context of the
 | 
			
		||||
  # parent of the bound data object.  Resolution is attempted firstly as keys
 | 
			
		||||
  # in #parameters, and secondly as methods in this parent.  This
 | 
			
		||||
  # resolution propagates up the chain of parent data objects.
 | 
			
		||||
  #
 | 
			
		||||
  # An evaluation will recurse until it returns a result that is not
 | 
			
		||||
  # a lambda or a symbol.
 | 
			
		||||
  #
 | 
			
		||||
  # This resolution process makes the lambda easier to read as we just write
 | 
			
		||||
  # <tt>field</tt> instead of <tt>obj.field</tt>.
 | 
			
		||||
  class LazyEvaluator
 | 
			
		||||
 | 
			
		||||
    # Creates a new evaluator.  All lazy evaluation is performed in the
 | 
			
		||||
    # context of +obj+.
 | 
			
		||||
    def initialize(obj)
 | 
			
		||||
      @obj = obj
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def lazy_eval(val, overrides = nil)
 | 
			
		||||
      @overrides = overrides if overrides
 | 
			
		||||
      if val.is_a? Symbol
 | 
			
		||||
        __send__(val)
 | 
			
		||||
      elsif callable?(val)
 | 
			
		||||
        instance_exec(&val)
 | 
			
		||||
      else
 | 
			
		||||
        val
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a LazyEvaluator for the parent of this data object.
 | 
			
		||||
    def parent
 | 
			
		||||
      if @obj.parent
 | 
			
		||||
        @obj.parent.lazy_evaluator
 | 
			
		||||
      else
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the index of this data object inside it's nearest container
 | 
			
		||||
    # array.
 | 
			
		||||
    def index
 | 
			
		||||
      return @overrides[:index] if defined?(@overrides) && @overrides.key?(:index)
 | 
			
		||||
 | 
			
		||||
      child = @obj
 | 
			
		||||
      parent = @obj.parent
 | 
			
		||||
      while parent
 | 
			
		||||
        if parent.respond_to?(:find_index_of)
 | 
			
		||||
          return parent.find_index_of(child)
 | 
			
		||||
        end
 | 
			
		||||
        child = parent
 | 
			
		||||
        parent = parent.parent
 | 
			
		||||
      end
 | 
			
		||||
      raise NoMethodError, "no index found"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args)
 | 
			
		||||
      return @overrides[symbol] if defined?(@overrides) && @overrides.key?(symbol)
 | 
			
		||||
 | 
			
		||||
      if @obj.parent
 | 
			
		||||
        eval_symbol_in_parent_context(symbol, args)
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def eval_symbol_in_parent_context(symbol, args)
 | 
			
		||||
      result = resolve_symbol_in_parent_context(symbol, args)
 | 
			
		||||
      recursively_eval(result, args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def resolve_symbol_in_parent_context(symbol, args)
 | 
			
		||||
      obj_parent = @obj.parent
 | 
			
		||||
 | 
			
		||||
      if obj_parent.has_parameter?(symbol)
 | 
			
		||||
        obj_parent.get_parameter(symbol)
 | 
			
		||||
      elsif obj_parent.safe_respond_to?(symbol, true)
 | 
			
		||||
        obj_parent.__send__(symbol, *args)
 | 
			
		||||
      else
 | 
			
		||||
        symbol
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def recursively_eval(val, args)
 | 
			
		||||
      if val.is_a?(Symbol)
 | 
			
		||||
        parent.__send__(val, *args)
 | 
			
		||||
      elsif callable?(val)
 | 
			
		||||
        parent.instance_exec(&val)
 | 
			
		||||
      else
 | 
			
		||||
        val
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def callable?(obj)
 | 
			
		||||
      Proc === obj || Method === obj || UnboundMethod === obj
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										28
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/name.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/name.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These parameters are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:name</tt>:: The name that this object can be referred to may be
 | 
			
		||||
  #                  set explicitly.  This is only useful when dynamically
 | 
			
		||||
  #                  generating types.
 | 
			
		||||
  #                  <code><pre>
 | 
			
		||||
  #                    BinData::Struct.new(name: :my_struct, fields: ...)
 | 
			
		||||
  #                    array = BinData::Array.new(type: :my_struct)
 | 
			
		||||
  #                  </pre></code>
 | 
			
		||||
  module RegisterNamePlugin
 | 
			
		||||
 | 
			
		||||
    def self.included(base) #:nodoc:
 | 
			
		||||
      # The registered name may be provided explicitly.
 | 
			
		||||
      base.optional_parameter :name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      if has_parameter?(:name)
 | 
			
		||||
        RegisteredClasses.register(get_parameter(:name), self)
 | 
			
		||||
      end
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										94
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/offset.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/offset.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # WARNING: THIS IS UNSUPPORTED!!
 | 
			
		||||
  #
 | 
			
		||||
  # This was a (failed) experimental feature that allowed seeking within the
 | 
			
		||||
  # input stream.  It remains here for backwards compatability for the few
 | 
			
		||||
  # people that used it.
 | 
			
		||||
  #
 | 
			
		||||
  # The official way to skip around the stream is to use BinData::Skip with
 | 
			
		||||
  # the `:to_abs_offset` parameter.
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These parameters are:
 | 
			
		||||
  #
 | 
			
		||||
  # [<tt>:check_offset</tt>]  Raise an error if the current IO offset doesn't
 | 
			
		||||
  #                           meet this criteria.  A boolean return indicates
 | 
			
		||||
  #                           success or failure.  Any other return is compared
 | 
			
		||||
  #                           to the current offset.  The variable +offset+
 | 
			
		||||
  #                           is made available to any lambda assigned to
 | 
			
		||||
  #                           this parameter.  This parameter is only checked
 | 
			
		||||
  #                           before reading.
 | 
			
		||||
  # [<tt>:adjust_offset</tt>] Ensures that the current IO offset is at this
 | 
			
		||||
  #                           position before reading.  This is like
 | 
			
		||||
  #                           <tt>:check_offset</tt>, except that it will
 | 
			
		||||
  #                           adjust the IO offset instead of raising an error.
 | 
			
		||||
  module CheckOrAdjustOffsetPlugin
 | 
			
		||||
 | 
			
		||||
    def self.included(base) #:nodoc:
 | 
			
		||||
      base.optional_parameters :check_offset, :adjust_offset
 | 
			
		||||
      base.mutually_exclusive_parameters :check_offset, :adjust_offset
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      extend CheckOffsetMixin  if has_parameter?(:check_offset)
 | 
			
		||||
      extend AdjustOffsetMixin if has_parameter?(:adjust_offset)
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module CheckOffsetMixin
 | 
			
		||||
      def do_read(io) #:nodoc:
 | 
			
		||||
        check_offset(io)
 | 
			
		||||
        super(io)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #---------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def check_offset(io)
 | 
			
		||||
        actual_offset = io.offset
 | 
			
		||||
        expected = eval_parameter(:check_offset, offset: actual_offset)
 | 
			
		||||
 | 
			
		||||
        if !expected
 | 
			
		||||
          raise ValidityError, "offset not as expected for #{debug_name}"
 | 
			
		||||
        elsif actual_offset != expected && expected != true
 | 
			
		||||
          raise ValidityError,
 | 
			
		||||
                "offset is '#{actual_offset}' but " +
 | 
			
		||||
                "expected '#{expected}' for #{debug_name}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    module AdjustOffsetMixin
 | 
			
		||||
      def do_read(io) #:nodoc:
 | 
			
		||||
        adjust_offset(io)
 | 
			
		||||
        super(io)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #---------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def adjust_offset(io)
 | 
			
		||||
        actual_offset = io.offset
 | 
			
		||||
        expected = eval_parameter(:adjust_offset)
 | 
			
		||||
        if actual_offset != expected
 | 
			
		||||
          begin
 | 
			
		||||
            seek = expected - actual_offset
 | 
			
		||||
            io.seekbytes(seek)
 | 
			
		||||
            warn "adjusting stream position by #{seek} bytes" if $VERBOSE
 | 
			
		||||
          rescue
 | 
			
		||||
            raise ValidityError,
 | 
			
		||||
                  "offset is '#{actual_offset}' but couldn't seek to " +
 | 
			
		||||
                  "expected '#{expected}' for #{debug_name}"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Add these offset options to Base
 | 
			
		||||
  class Base
 | 
			
		||||
    include CheckOrAdjustOffsetPlugin
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										128
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/params.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/params.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
			
		||||
require 'bindata/lazy'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  module AcceptedParametersPlugin
 | 
			
		||||
    # Mandatory parameters must be present when instantiating a data object.
 | 
			
		||||
    def mandatory_parameters(*args)
 | 
			
		||||
      accepted_parameters.mandatory(*args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Optional parameters may be present when instantiating a data object.
 | 
			
		||||
    def optional_parameters(*args)
 | 
			
		||||
      accepted_parameters.optional(*args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Default parameters can be overridden when instantiating a data object.
 | 
			
		||||
    def default_parameters(*args)
 | 
			
		||||
      accepted_parameters.default(*args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Mutually exclusive parameters may not all be present when
 | 
			
		||||
    # instantiating a data object.
 | 
			
		||||
    def mutually_exclusive_parameters(*args)
 | 
			
		||||
      accepted_parameters.mutually_exclusive(*args)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alias mandatory_parameter mandatory_parameters
 | 
			
		||||
    alias optional_parameter  optional_parameters
 | 
			
		||||
    alias default_parameter   default_parameters
 | 
			
		||||
 | 
			
		||||
    def accepted_parameters #:nodoc:
 | 
			
		||||
      @accepted_parameters ||= begin
 | 
			
		||||
        ancestor_params = superclass.respond_to?(:accepted_parameters) ?
 | 
			
		||||
                            superclass.accepted_parameters : nil
 | 
			
		||||
        AcceptedParameters.new(ancestor_params)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # BinData objects accept parameters when initializing.  AcceptedParameters
 | 
			
		||||
    # allow a BinData class to declaratively identify accepted parameters as
 | 
			
		||||
    # mandatory, optional, default or mutually exclusive.
 | 
			
		||||
    class AcceptedParameters
 | 
			
		||||
      def initialize(ancestor_parameters = nil)
 | 
			
		||||
        if ancestor_parameters
 | 
			
		||||
          @mandatory = ancestor_parameters.mandatory.dup
 | 
			
		||||
          @optional  = ancestor_parameters.optional.dup
 | 
			
		||||
          @default   = ancestor_parameters.default.dup
 | 
			
		||||
          @mutually_exclusive = ancestor_parameters.mutually_exclusive.dup
 | 
			
		||||
        else
 | 
			
		||||
          @mandatory = []
 | 
			
		||||
          @optional  = []
 | 
			
		||||
          @default   = Hash.new
 | 
			
		||||
          @mutually_exclusive = []
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def mandatory(*args)
 | 
			
		||||
        unless args.empty?
 | 
			
		||||
          @mandatory.concat(to_syms(args))
 | 
			
		||||
          @mandatory.uniq!
 | 
			
		||||
        end
 | 
			
		||||
        @mandatory
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def optional(*args)
 | 
			
		||||
        unless args.empty?
 | 
			
		||||
          @optional.concat(to_syms(args))
 | 
			
		||||
          @optional.uniq!
 | 
			
		||||
        end
 | 
			
		||||
        @optional
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def default(args = nil)
 | 
			
		||||
        if args
 | 
			
		||||
          to_syms(args.keys)  # call for side effect of validating names
 | 
			
		||||
          args.each_pair do |param, value|
 | 
			
		||||
            @default[param.to_sym] = value
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        @default
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def mutually_exclusive(*args)
 | 
			
		||||
        arg1 = args.shift
 | 
			
		||||
        until args.empty?
 | 
			
		||||
          args.each do |arg2|
 | 
			
		||||
            @mutually_exclusive.push([arg1.to_sym, arg2.to_sym])
 | 
			
		||||
            @mutually_exclusive.uniq!
 | 
			
		||||
          end
 | 
			
		||||
          arg1 = args.shift
 | 
			
		||||
        end
 | 
			
		||||
        @mutually_exclusive
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def all
 | 
			
		||||
        (@mandatory + @optional + @default.keys).uniq
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      #---------------
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def to_syms(args)
 | 
			
		||||
        syms = args.collect(&:to_sym)
 | 
			
		||||
        ensure_valid_names(syms)
 | 
			
		||||
        syms
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def ensure_valid_names(names)
 | 
			
		||||
        invalid_names = self.class.invalid_parameter_names
 | 
			
		||||
        names.each do |name|
 | 
			
		||||
          if invalid_names.include?(name)
 | 
			
		||||
            raise NameError.new("Rename parameter '#{name}' " \
 | 
			
		||||
                                "as it shadows an existing method.", name)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def self.invalid_parameter_names
 | 
			
		||||
        @invalid_names ||= begin
 | 
			
		||||
          all_names = LazyEvaluator.instance_methods(true) + Kernel.methods
 | 
			
		||||
          allowed_names = [:name, :type]
 | 
			
		||||
          invalid_names = (all_names - allowed_names).uniq
 | 
			
		||||
 | 
			
		||||
          Hash[*invalid_names.collect { |key| [key.to_sym, true] }.flatten]
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										143
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/primitive.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/primitive.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,143 @@
 | 
			
		||||
require 'bindata/base_primitive'
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
require 'bindata/struct'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A Primitive is a declarative way to define a new BinData data type.
 | 
			
		||||
  # The data type must contain a primitive value only, i.e numbers or strings.
 | 
			
		||||
  # For new data types that contain multiple values see BinData::Record.
 | 
			
		||||
  #
 | 
			
		||||
  # To define a new data type, set fields as if for Record and add a
 | 
			
		||||
  # #get and #set method to extract / convert the data between the fields
 | 
			
		||||
  # and the #value of the object.
 | 
			
		||||
  #
 | 
			
		||||
  #    require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #    class PascalString < BinData::Primitive
 | 
			
		||||
  #      uint8  :len,  value: -> { data.length }
 | 
			
		||||
  #      string :data, read_length: :len
 | 
			
		||||
  #
 | 
			
		||||
  #      def get
 | 
			
		||||
  #        self.data
 | 
			
		||||
  #      end
 | 
			
		||||
  #
 | 
			
		||||
  #      def set(v)
 | 
			
		||||
  #        self.data = v
 | 
			
		||||
  #      end
 | 
			
		||||
  #    end
 | 
			
		||||
  #
 | 
			
		||||
  #    ps = PascalString.new(initial_value: "hello")
 | 
			
		||||
  #    ps.to_binary_s #=> "\005hello"
 | 
			
		||||
  #    ps.read("\003abcde")
 | 
			
		||||
  #    ps #=> "abc"
 | 
			
		||||
  #
 | 
			
		||||
  #    # Unsigned 24 bit big endian integer
 | 
			
		||||
  #    class Uint24be < BinData::Primitive
 | 
			
		||||
  #      uint8 :byte1
 | 
			
		||||
  #      uint8 :byte2
 | 
			
		||||
  #      uint8 :byte3
 | 
			
		||||
  #
 | 
			
		||||
  #      def get
 | 
			
		||||
  #        (self.byte1 << 16) | (self.byte2 << 8) | self.byte3
 | 
			
		||||
  #      end
 | 
			
		||||
  #
 | 
			
		||||
  #      def set(v)
 | 
			
		||||
  #        v = 0 if v < 0
 | 
			
		||||
  #        v = 0xffffff if v > 0xffffff
 | 
			
		||||
  #
 | 
			
		||||
  #        self.byte1 = (v >> 16) & 0xff
 | 
			
		||||
  #        self.byte2 = (v >>  8) & 0xff
 | 
			
		||||
  #        self.byte3 =  v        & 0xff
 | 
			
		||||
  #      end
 | 
			
		||||
  #    end
 | 
			
		||||
  #
 | 
			
		||||
  #    u24 = Uint24be.new
 | 
			
		||||
  #    u24.read("\x12\x34\x56")
 | 
			
		||||
  #    "0x%x" % u24 #=> 0x123456
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Primitive objects accept all the parameters that BinData::BasePrimitive do.
 | 
			
		||||
  #
 | 
			
		||||
  class Primitive < BasePrimitive
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
 | 
			
		||||
    unregister_self
 | 
			
		||||
    dsl_parser    :primitive
 | 
			
		||||
    arg_processor :primitive
 | 
			
		||||
 | 
			
		||||
    mandatory_parameter :struct_params
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      super
 | 
			
		||||
      @struct = BinData::Struct.new(get_parameter(:struct_params), self)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def respond_to?(symbol, include_private = false) #:nodoc:
 | 
			
		||||
      @struct.respond_to?(symbol, include_private) || super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def method_missing(symbol, *args, &block) #:nodoc:
 | 
			
		||||
      if @struct.respond_to?(symbol)
 | 
			
		||||
        @struct.__send__(symbol, *args, &block)
 | 
			
		||||
      else
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      super(val)
 | 
			
		||||
      set(_value)
 | 
			
		||||
      @value = get
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def debug_name_of(child) #:nodoc:
 | 
			
		||||
      debug_name + "-internal-"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io)
 | 
			
		||||
      set(_value)
 | 
			
		||||
      @struct.do_write(io)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes
 | 
			
		||||
      set(_value)
 | 
			
		||||
      @struct.do_num_bytes
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      get
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      @struct.do_read(io)
 | 
			
		||||
      get
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ###########################################################################
 | 
			
		||||
    # To be implemented by subclasses
 | 
			
		||||
 | 
			
		||||
    # Extracts the value for this data object from the fields of the
 | 
			
		||||
    # internal struct.
 | 
			
		||||
    def get
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets the fields of the internal struct to represent +v+.
 | 
			
		||||
    def set(v)
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # To be implemented by subclasses
 | 
			
		||||
    ###########################################################################
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class PrimitiveArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      params[:struct_params] = params.create_sanitized_params(obj_class.dsl_params, BinData::Struct)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										23
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/record.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/record.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
require 'bindata/dsl'
 | 
			
		||||
require 'bindata/struct'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A Record is a declarative wrapper around Struct.
 | 
			
		||||
  #
 | 
			
		||||
  # See +Struct+ for more info.
 | 
			
		||||
  class Record < BinData::Struct
 | 
			
		||||
    extend DSLMixin
 | 
			
		||||
 | 
			
		||||
    unregister_self
 | 
			
		||||
    dsl_parser    :struct
 | 
			
		||||
    arg_processor :record
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class RecordArgProcessor < StructArgProcessor
 | 
			
		||||
    include MultiFieldArgSeparator
 | 
			
		||||
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      super(obj_class, params.merge!(obj_class.dsl_params))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										134
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/registry.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/registry.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
			
		||||
module BinData
 | 
			
		||||
 | 
			
		||||
  class UnRegisteredTypeError < StandardError ; end
 | 
			
		||||
 | 
			
		||||
  # This registry contains a register of name -> class mappings.
 | 
			
		||||
  #
 | 
			
		||||
  # Numerics (integers and floating point numbers) have an endian property as
 | 
			
		||||
  # part of their name (e.g. int32be, float_le).
 | 
			
		||||
  #
 | 
			
		||||
  # Classes can be looked up based on their full name or an abbreviated +name+
 | 
			
		||||
  # with +hints+.
 | 
			
		||||
  #
 | 
			
		||||
  # There are two hints supported, :endian and :search_prefix.
 | 
			
		||||
  #
 | 
			
		||||
  #   #lookup("int32", { endian: :big }) will return Int32Be.
 | 
			
		||||
  #
 | 
			
		||||
  #   #lookup("my_type", { search_prefix: :ns }) will return NsMyType.
 | 
			
		||||
  #
 | 
			
		||||
  # Names are stored in under_score_style, not camelCase.
 | 
			
		||||
  class Registry
 | 
			
		||||
 | 
			
		||||
    def initialize
 | 
			
		||||
      @registry = {}
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def register(name, class_to_register)
 | 
			
		||||
      return if name.nil? || class_to_register.nil?
 | 
			
		||||
 | 
			
		||||
      formatted_name = underscore_name(name)
 | 
			
		||||
      warn_if_name_is_already_registered(formatted_name, class_to_register)
 | 
			
		||||
 | 
			
		||||
      @registry[formatted_name] = class_to_register
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def unregister(name)
 | 
			
		||||
      @registry.delete(underscore_name(name))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def lookup(name, hints = {})
 | 
			
		||||
      the_class = @registry[normalize_name(name, hints)]
 | 
			
		||||
      if the_class
 | 
			
		||||
        the_class
 | 
			
		||||
      elsif @registry[normalize_name(name, hints.merge(endian: :big))]
 | 
			
		||||
        raise(UnRegisteredTypeError, "#{name}, do you need to specify endian?")
 | 
			
		||||
      else
 | 
			
		||||
        raise(UnRegisteredTypeError, name)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Convert CamelCase +name+ to underscore style.
 | 
			
		||||
    def underscore_name(name)
 | 
			
		||||
      name.
 | 
			
		||||
        to_s.
 | 
			
		||||
        sub(/.*::/, "").
 | 
			
		||||
        gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
 | 
			
		||||
        gsub(/([a-z\d])([A-Z])/, '\1_\2').
 | 
			
		||||
        tr("-", "_").
 | 
			
		||||
        downcase
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def normalize_name(name, hints)
 | 
			
		||||
      name = underscore_name(name)
 | 
			
		||||
 | 
			
		||||
      if !registered?(name)
 | 
			
		||||
        search_prefix = [""].concat(Array(hints[:search_prefix]))
 | 
			
		||||
        search_prefix.each do |prefix|
 | 
			
		||||
          nwp = name_with_prefix(name, prefix)
 | 
			
		||||
          if registered?(nwp)
 | 
			
		||||
            name = nwp
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          nwe = name_with_endian(nwp, hints[:endian])
 | 
			
		||||
          if registered?(nwe)
 | 
			
		||||
            name = nwe
 | 
			
		||||
            break
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name_with_prefix(name, prefix)
 | 
			
		||||
      prefix = prefix.to_s.chomp("_")
 | 
			
		||||
      if prefix == ""
 | 
			
		||||
        name
 | 
			
		||||
      else
 | 
			
		||||
        "#{prefix}_#{name}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name_with_endian(name, endian)
 | 
			
		||||
      return name if endian.nil?
 | 
			
		||||
 | 
			
		||||
      suffix = (endian == :little) ? "le" : "be"
 | 
			
		||||
      if /^u?int\d+$/ =~ name
 | 
			
		||||
        name + suffix
 | 
			
		||||
      else
 | 
			
		||||
        name + "_" + suffix
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def registered?(name)
 | 
			
		||||
      register_dynamic_class(name) unless @registry.key?(name)
 | 
			
		||||
 | 
			
		||||
      @registry.key?(name)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def register_dynamic_class(name)
 | 
			
		||||
      if /^u?int\d+(le|be)$/ =~ name || /^s?bit\d+(le)?$/ =~ name
 | 
			
		||||
        class_name = name.gsub(/(?:^|_)(.)/) { $1.upcase }
 | 
			
		||||
        begin
 | 
			
		||||
          BinData.const_get(class_name)
 | 
			
		||||
        rescue NameError
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def warn_if_name_is_already_registered(name, class_to_register)
 | 
			
		||||
      prev_class = @registry[name]
 | 
			
		||||
      if $VERBOSE && prev_class && prev_class != class_to_register
 | 
			
		||||
        warn "warning: replacing registered class #{prev_class} " \
 | 
			
		||||
             "with #{class_to_register}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # A singleton registry of all registered classes.
 | 
			
		||||
  RegisteredClasses = Registry.new
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										34
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/rest.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/rest.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Rest will consume the input stream from the current position to the end of
 | 
			
		||||
  # the stream.  This will mainly be useful for debugging and developing.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   class A < BinData::Record
 | 
			
		||||
  #     string :a, read_length: 5
 | 
			
		||||
  #     rest   :rest
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = A.read("abcdefghij")
 | 
			
		||||
  #   obj.a #=> "abcde"
 | 
			
		||||
  #   obj.rest #=" "fghij"
 | 
			
		||||
  #
 | 
			
		||||
  class Rest < BinData::BasePrimitive
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      val
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      io.read_all_bytes
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										372
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/sanitize.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/sanitize.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,372 @@
 | 
			
		||||
require 'bindata/registry'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
 | 
			
		||||
  # Subclasses of this are sanitized
 | 
			
		||||
  class SanitizedParameter; end
 | 
			
		||||
 | 
			
		||||
  class SanitizedPrototype < SanitizedParameter
 | 
			
		||||
    def initialize(obj_type, obj_params, hints)
 | 
			
		||||
      raw_hints = hints.dup
 | 
			
		||||
      if raw_hints[:endian].respond_to?(:endian)
 | 
			
		||||
        raw_hints[:endian] = raw_hints[:endian].endian
 | 
			
		||||
      end
 | 
			
		||||
      obj_params ||= {}
 | 
			
		||||
 | 
			
		||||
      if BinData::Base === obj_type
 | 
			
		||||
        obj_class = obj_type
 | 
			
		||||
      else
 | 
			
		||||
        obj_class = RegisteredClasses.lookup(obj_type, raw_hints)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if BinData::Base === obj_class
 | 
			
		||||
        @factory = obj_class
 | 
			
		||||
      else
 | 
			
		||||
        @obj_class  = obj_class
 | 
			
		||||
        @obj_params = SanitizedParameters.new(obj_params, @obj_class, hints)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def has_parameter?(param)
 | 
			
		||||
      if defined? @factory
 | 
			
		||||
        @factory.has_parameter?(param)
 | 
			
		||||
      else
 | 
			
		||||
        @obj_params.has_parameter?(param)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def instantiate(value = nil, parent = nil)
 | 
			
		||||
      @factory ||= @obj_class.new(@obj_params)
 | 
			
		||||
 | 
			
		||||
      @factory.new(value, parent)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  class SanitizedField < SanitizedParameter
 | 
			
		||||
    def initialize(name, field_type, field_params, hints)
 | 
			
		||||
      @name      = name
 | 
			
		||||
      @prototype = SanitizedPrototype.new(field_type, field_params, hints)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    attr_reader :prototype
 | 
			
		||||
 | 
			
		||||
    def name_as_sym
 | 
			
		||||
      @name.nil? ? nil : @name.to_sym
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def name
 | 
			
		||||
      @name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def has_parameter?(param)
 | 
			
		||||
      @prototype.has_parameter?(param)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def instantiate(value = nil, parent = nil)
 | 
			
		||||
      @prototype.instantiate(value, parent)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  class SanitizedFields < SanitizedParameter
 | 
			
		||||
    include Enumerable
 | 
			
		||||
 | 
			
		||||
    def initialize(hints, base_fields = nil)
 | 
			
		||||
      @hints = hints
 | 
			
		||||
      if base_fields
 | 
			
		||||
        @fields = base_fields.raw_fields
 | 
			
		||||
      else
 | 
			
		||||
        @fields = []
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def add_field(type, name, params)
 | 
			
		||||
      name = nil if name == ""
 | 
			
		||||
 | 
			
		||||
      @fields << SanitizedField.new(name, type, params, @hints)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def raw_fields
 | 
			
		||||
      @fields.dup
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](idx)
 | 
			
		||||
      @fields[idx]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def empty?
 | 
			
		||||
      @fields.empty?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def length
 | 
			
		||||
      @fields.length
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def each(&block)
 | 
			
		||||
      @fields.each(&block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def field_names
 | 
			
		||||
      @fields.collect(&:name_as_sym)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def field_name?(name)
 | 
			
		||||
      @fields.detect { |f| f.name_as_sym == name.to_sym }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def all_field_names_blank?
 | 
			
		||||
      @fields.all? { |f| f.name.nil? }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def no_field_names_blank?
 | 
			
		||||
      @fields.all? { |f| f.name != nil }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def any_field_has_parameter?(parameter)
 | 
			
		||||
      @fields.any? { |f| f.has_parameter?(parameter) }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  class SanitizedChoices < SanitizedParameter
 | 
			
		||||
    def initialize(choices, hints)
 | 
			
		||||
      @choices = {}
 | 
			
		||||
      choices.each_pair do |key, val|
 | 
			
		||||
        if SanitizedParameter === val
 | 
			
		||||
          prototype = val
 | 
			
		||||
        else
 | 
			
		||||
          type, param = val
 | 
			
		||||
          prototype = SanitizedPrototype.new(type, param, hints)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if key == :default
 | 
			
		||||
          @choices.default = prototype
 | 
			
		||||
        else
 | 
			
		||||
          @choices[key] = prototype
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](key)
 | 
			
		||||
      @choices[key]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  class SanitizedBigEndian < SanitizedParameter
 | 
			
		||||
    def endian
 | 
			
		||||
      :big
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class SanitizedLittleEndian < SanitizedParameter
 | 
			
		||||
    def endian
 | 
			
		||||
      :little
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  # BinData objects are instantiated with parameters to determine their
 | 
			
		||||
  # behaviour.  These parameters must be sanitized to ensure their values
 | 
			
		||||
  # are valid.  When instantiating many objects with identical parameters,
 | 
			
		||||
  # such as an array of records, there is much duplicated sanitizing.
 | 
			
		||||
  #
 | 
			
		||||
  # The purpose of the sanitizing code is to eliminate the duplicated
 | 
			
		||||
  # validation.
 | 
			
		||||
  #
 | 
			
		||||
  # SanitizedParameters is a hash-like collection of parameters.  Its purpose
 | 
			
		||||
  # is to recursively sanitize the parameters of an entire BinData object chain
 | 
			
		||||
  # at a single time.
 | 
			
		||||
  class SanitizedParameters < Hash
 | 
			
		||||
 | 
			
		||||
    # Memoized constants
 | 
			
		||||
    BIG_ENDIAN    = SanitizedBigEndian.new
 | 
			
		||||
    LITTLE_ENDIAN = SanitizedLittleEndian.new
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
      def sanitize(parameters, the_class)
 | 
			
		||||
        if SanitizedParameters === parameters
 | 
			
		||||
          parameters
 | 
			
		||||
        else
 | 
			
		||||
          SanitizedParameters.new(parameters, the_class, {})
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize(parameters, the_class, hints)
 | 
			
		||||
      parameters.each_pair { |key, value| self[key.to_sym] = value }
 | 
			
		||||
 | 
			
		||||
      @the_class = the_class
 | 
			
		||||
 | 
			
		||||
      if hints[:endian]
 | 
			
		||||
        self[:endian] ||= hints[:endian]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if hints[:search_prefix] && !hints[:search_prefix].empty?
 | 
			
		||||
        self[:search_prefix] = Array(self[:search_prefix]).concat(Array(hints[:search_prefix]))
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      sanitize!
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    alias_method :has_parameter?, :key?
 | 
			
		||||
 | 
			
		||||
    def has_at_least_one_of?(*keys)
 | 
			
		||||
      keys.each do |key|
 | 
			
		||||
        return true if has_parameter?(key)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def warn_replacement_parameter(bad_key, suggested_key)
 | 
			
		||||
      if has_parameter?(bad_key)
 | 
			
		||||
        Kernel.warn ":#{bad_key} is not used with #{@the_class}.  " \
 | 
			
		||||
                    "You probably want to change this to :#{suggested_key}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
#    def warn_renamed_parameter(old_key, new_key)
 | 
			
		||||
#      val = delete(old_key)
 | 
			
		||||
#      if val
 | 
			
		||||
#        self[new_key] = val
 | 
			
		||||
#        Kernel.warn ":#{old_key} has been renamed to :#{new_key} in #{@the_class}.  " \
 | 
			
		||||
#        "Using :#{old_key} is now deprecated and will be removed in the future"
 | 
			
		||||
#      end
 | 
			
		||||
#    end
 | 
			
		||||
 | 
			
		||||
    def must_be_integer(*keys)
 | 
			
		||||
      keys.each do |key|
 | 
			
		||||
        if has_parameter?(key)
 | 
			
		||||
          parameter = self[key]
 | 
			
		||||
          unless Symbol === parameter ||
 | 
			
		||||
                 parameter.respond_to?(:arity) ||
 | 
			
		||||
                 parameter.respond_to?(:to_int)
 | 
			
		||||
            raise ArgumentError, "parameter '#{key}' in #{@the_class} must " \
 | 
			
		||||
                                 "evaluate to an integer, got #{parameter.class}"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def rename_parameter(old_key, new_key)
 | 
			
		||||
      if has_parameter?(old_key)
 | 
			
		||||
        self[new_key] = delete(old_key)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_object_prototype(key)
 | 
			
		||||
      sanitize(key) { |obj_type, obj_params| create_sanitized_object_prototype(obj_type, obj_params) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_fields(key, &block)
 | 
			
		||||
      sanitize(key) do |fields|
 | 
			
		||||
        sanitized_fields = create_sanitized_fields
 | 
			
		||||
        yield(fields, sanitized_fields)
 | 
			
		||||
        sanitized_fields
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_choices(key, &block)
 | 
			
		||||
      sanitize(key) do |obj|
 | 
			
		||||
        create_sanitized_choices(yield(obj))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_endian(key)
 | 
			
		||||
      sanitize(key) { |endian| create_sanitized_endian(endian) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize(key, &block)
 | 
			
		||||
      if needs_sanitizing?(key)
 | 
			
		||||
        self[key] = yield(self[key])
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_sanitized_params(params, the_class)
 | 
			
		||||
      SanitizedParameters.new(params, the_class, hints)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def hints
 | 
			
		||||
      { endian: self[:endian], search_prefix: self[:search_prefix] }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def sanitize!
 | 
			
		||||
      ensure_no_nil_values
 | 
			
		||||
      merge_default_parameters!
 | 
			
		||||
 | 
			
		||||
      @the_class.arg_processor.sanitize_parameters!(@the_class, self)
 | 
			
		||||
 | 
			
		||||
      ensure_mandatory_parameters_exist
 | 
			
		||||
      ensure_mutual_exclusion_of_parameters
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def needs_sanitizing?(key)
 | 
			
		||||
      has_key?(key) && ! self[key].is_a?(SanitizedParameter)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ensure_no_nil_values
 | 
			
		||||
      each do |key, value|
 | 
			
		||||
        if value.nil?
 | 
			
		||||
          raise ArgumentError,
 | 
			
		||||
                "parameter '#{key}' has nil value in #{@the_class}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def merge_default_parameters!
 | 
			
		||||
      @the_class.default_parameters.each do |key, value|
 | 
			
		||||
        self[key] = value unless has_key?(key)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ensure_mandatory_parameters_exist
 | 
			
		||||
      @the_class.mandatory_parameters.each do |key|
 | 
			
		||||
        unless has_parameter?(key)
 | 
			
		||||
          raise ArgumentError,
 | 
			
		||||
                  "parameter '#{key}' must be specified in #{@the_class}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ensure_mutual_exclusion_of_parameters
 | 
			
		||||
      return if length < 2
 | 
			
		||||
 | 
			
		||||
      @the_class.mutually_exclusive_parameters.each do |key1, key2|
 | 
			
		||||
        if has_parameter?(key1) && has_parameter?(key2)
 | 
			
		||||
          raise ArgumentError, "params '#{key1}' and '#{key2}' " \
 | 
			
		||||
                               "are mutually exclusive in #{@the_class}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_sanitized_endian(endian)
 | 
			
		||||
      if endian == :big
 | 
			
		||||
        BIG_ENDIAN
 | 
			
		||||
      elsif endian == :little
 | 
			
		||||
        LITTLE_ENDIAN
 | 
			
		||||
      elsif endian == :big_and_little
 | 
			
		||||
        raise ArgumentError, "endian: :big or endian: :little is required"
 | 
			
		||||
      else
 | 
			
		||||
        raise ArgumentError, "unknown value for endian '#{endian}'"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_sanitized_choices(choices)
 | 
			
		||||
      SanitizedChoices.new(choices, hints)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_sanitized_fields
 | 
			
		||||
      SanitizedFields.new(hints)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_sanitized_object_prototype(obj_type, obj_params)
 | 
			
		||||
      SanitizedPrototype.new(obj_type, obj_params, hints)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  #----------------------------------------------------------------------------
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										133
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/skip.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/skip.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Skip will skip over bytes from the input stream.  If the stream is not
 | 
			
		||||
  # seekable, then the bytes are consumed and discarded.
 | 
			
		||||
  #
 | 
			
		||||
  # When writing, skip will write the appropriate number of zero bytes.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   class A < BinData::Record
 | 
			
		||||
  #     skip length: 5
 | 
			
		||||
  #     string :a, read_length: 5
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = A.read("abcdefghij")
 | 
			
		||||
  #   obj.a #=> "fghij"
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  #   class B < BinData::Record
 | 
			
		||||
  #     skip until_valid: [:string, {read_length: 2, assert: "ef"} ]
 | 
			
		||||
  #     string :b, read_length: 5
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = B.read("abcdefghij")
 | 
			
		||||
  #   obj.b #=> "efghi"
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Skip objects accept all the params that BinData::BasePrimitive
 | 
			
		||||
  # does, as well as the following:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:length</tt>::        The number of bytes to skip.
 | 
			
		||||
  # <tt>:to_abs_offset</tt>:: Skips to the given absolute offset.
 | 
			
		||||
  # <tt>:until_valid</tt>::   Skips untils a given byte pattern is matched.
 | 
			
		||||
  #                           This parameter contains a type that will raise
 | 
			
		||||
  #                           a BinData::ValidityError unless an acceptable byte
 | 
			
		||||
  #                           sequence is found.  The type is represented by a
 | 
			
		||||
  #                           Symbol, or if the type is to have params #
 | 
			
		||||
  #                           passed to it, then it should be provided as #
 | 
			
		||||
  #                           <tt>[type_symbol, hash_params]</tt>.
 | 
			
		||||
  #
 | 
			
		||||
  class Skip < BinData::BasePrimitive
 | 
			
		||||
    arg_processor :skip
 | 
			
		||||
 | 
			
		||||
    optional_parameters :length, :to_abs_offset, :until_valid
 | 
			
		||||
    mutually_exclusive_parameters :length, :to_abs_offset, :until_valid
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      extend SkipLengthPlugin      if has_parameter?(:length)
 | 
			
		||||
      extend SkipToAbsOffsetPlugin if has_parameter?(:to_abs_offset)
 | 
			
		||||
      extend SkipUntilValidPlugin  if has_parameter?(:until_valid)
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      len = skip_length
 | 
			
		||||
      if len < 0
 | 
			
		||||
        raise ValidityError, "#{debug_name} attempted to seek backwards by #{len.abs} bytes"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      "\000" * skip_length
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      len = skip_length
 | 
			
		||||
      if len < 0
 | 
			
		||||
        raise ValidityError, "#{debug_name} attempted to seek backwards by #{len.abs} bytes"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      io.seekbytes(len)
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class SkipArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      unless params.has_at_least_one_of?(:length, :to_abs_offset, :until_valid)
 | 
			
		||||
        raise ArgumentError,
 | 
			
		||||
          "#{obj_class} requires either :length, :to_abs_offset or :until_valid"
 | 
			
		||||
      end
 | 
			
		||||
      params.must_be_integer(:to_abs_offset, :length)
 | 
			
		||||
      params.sanitize_object_prototype(:until_valid)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :length parameter
 | 
			
		||||
  module SkipLengthPlugin
 | 
			
		||||
    def skip_length
 | 
			
		||||
      eval_parameter(:length)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :to_abs_offset parameter
 | 
			
		||||
  module SkipToAbsOffsetPlugin
 | 
			
		||||
    def skip_length
 | 
			
		||||
      eval_parameter(:to_abs_offset) - abs_offset
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Logic for the :until_valid parameter
 | 
			
		||||
  module SkipUntilValidPlugin
 | 
			
		||||
    def skip_length
 | 
			
		||||
      # no skipping when writing
 | 
			
		||||
      0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      prototype = get_parameter(:until_valid)
 | 
			
		||||
      validator = prototype.instantiate(nil, self)
 | 
			
		||||
 | 
			
		||||
      valid = false
 | 
			
		||||
      until valid
 | 
			
		||||
        begin
 | 
			
		||||
          io.with_readahead do
 | 
			
		||||
            validator.read(io)
 | 
			
		||||
            valid = true
 | 
			
		||||
          end
 | 
			
		||||
        rescue ValidityError
 | 
			
		||||
          io.readbytes(1)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										153
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/string.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/string.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A String is a sequence of bytes.  This is the same as strings in Ruby 1.8.
 | 
			
		||||
  # The issue of character encoding is ignored by this class.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   data = "abcdefghij"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::String.new(read_length: 5)
 | 
			
		||||
  #   obj.read(data)
 | 
			
		||||
  #   obj #=> "abcde"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::String.new(length: 6)
 | 
			
		||||
  #   obj.read(data)
 | 
			
		||||
  #   obj #=> "abcdef"
 | 
			
		||||
  #   obj.assign("abcdefghij")
 | 
			
		||||
  #   obj #=> "abcdef"
 | 
			
		||||
  #   obj.assign("abcd")
 | 
			
		||||
  #   obj #=> "abcd\000\000"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::String.new(length: 6, trim_padding: true)
 | 
			
		||||
  #   obj.assign("abcd")
 | 
			
		||||
  #   obj #=> "abcd"
 | 
			
		||||
  #   obj.to_binary_s #=> "abcd\000\000"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::String.new(length: 6, pad_byte: 'A')
 | 
			
		||||
  #   obj.assign("abcd")
 | 
			
		||||
  #   obj #=> "abcdAA"
 | 
			
		||||
  #   obj.to_binary_s #=> "abcdAA"
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # String objects accept all the params that BinData::BasePrimitive
 | 
			
		||||
  # does, as well as the following:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:read_length</tt>::    The length in bytes to use when reading a value.
 | 
			
		||||
  # <tt>:length</tt>::         The fixed length of the string.  If a shorter
 | 
			
		||||
  #                            string is set, it will be padded to this length.
 | 
			
		||||
  # <tt>:pad_byte</tt>::       The byte to use when padding a string to a
 | 
			
		||||
  #                            set length.  Valid values are Integers and
 | 
			
		||||
  #                            Strings of length 1.  "\0" is the default.
 | 
			
		||||
  # <tt>:pad_front</tt>::      Signifies that the padding occurs at the front
 | 
			
		||||
  #                            of the string rather than the end.  Default
 | 
			
		||||
  #                            is false.
 | 
			
		||||
  # <tt>:trim_padding</tt>::   Boolean, default false.  If set, #value will
 | 
			
		||||
  #                            return the value with all pad_bytes trimmed
 | 
			
		||||
  #                            from the end of the string.  The value will
 | 
			
		||||
  #                            not be trimmed when writing.
 | 
			
		||||
  class String < BinData::BasePrimitive
 | 
			
		||||
    arg_processor :string
 | 
			
		||||
 | 
			
		||||
    optional_parameters :read_length, :length, :trim_padding, :pad_front, :pad_left
 | 
			
		||||
    default_parameters  pad_byte: "\0"
 | 
			
		||||
    mutually_exclusive_parameters :read_length, :length
 | 
			
		||||
    mutually_exclusive_parameters :length, :value
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      if (has_parameter?(:value) || has_parameter?(:asserted_value)) &&
 | 
			
		||||
          !has_parameter?(:read_length)
 | 
			
		||||
        extend WarnNoReadLengthPlugin
 | 
			
		||||
      end
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      super(binary_string(val))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      # override to trim padding
 | 
			
		||||
      snap = super
 | 
			
		||||
      snap = clamp_to_length(snap)
 | 
			
		||||
 | 
			
		||||
      if get_parameter(:trim_padding)
 | 
			
		||||
        trim_padding(snap)
 | 
			
		||||
      else
 | 
			
		||||
        snap
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def clamp_to_length(str)
 | 
			
		||||
      str = binary_string(str)
 | 
			
		||||
 | 
			
		||||
      len = eval_parameter(:length) || str.length
 | 
			
		||||
      if str.length == len
 | 
			
		||||
        str
 | 
			
		||||
      elsif str.length > len
 | 
			
		||||
        str.slice(0, len)
 | 
			
		||||
      else
 | 
			
		||||
        padding = (eval_parameter(:pad_byte) * (len - str.length))
 | 
			
		||||
        if get_parameter(:pad_front)
 | 
			
		||||
          padding + str
 | 
			
		||||
        else
 | 
			
		||||
          str + padding
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trim_padding(str)
 | 
			
		||||
      if get_parameter(:pad_front)
 | 
			
		||||
        str.sub(/\A#{eval_parameter(:pad_byte)}*/, "")
 | 
			
		||||
      else
 | 
			
		||||
        str.sub(/#{eval_parameter(:pad_byte)}*\z/, "")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      clamp_to_length(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      len = eval_parameter(:read_length) || eval_parameter(:length) || 0
 | 
			
		||||
      io.readbytes(len)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class StringArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      params.warn_replacement_parameter(:initial_length, :read_length)
 | 
			
		||||
      params.must_be_integer(:read_length, :length)
 | 
			
		||||
      params.rename_parameter(:pad_left, :pad_front)
 | 
			
		||||
      params.sanitize(:pad_byte) { |byte| sanitized_pad_byte(byte) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #-------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def sanitized_pad_byte(byte)
 | 
			
		||||
      pad_byte = byte.is_a?(Integer) ? byte.chr : byte.to_s
 | 
			
		||||
      if pad_byte.bytesize > 1
 | 
			
		||||
        raise ArgumentError, ":pad_byte must not contain more than 1 byte"
 | 
			
		||||
      end
 | 
			
		||||
      pad_byte
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Warns when reading if :value && no :read_length
 | 
			
		||||
  module WarnNoReadLengthPlugin
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      warn "#{debug_name} does not have a :read_length parameter - returning empty string"
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										96
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/stringz.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/stringz.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A BinData::Stringz object is a container for a zero ("\0") terminated
 | 
			
		||||
  # string.
 | 
			
		||||
  #
 | 
			
		||||
  # For convenience, the zero terminator is not necessary when setting the
 | 
			
		||||
  # value.  Likewise, the returned value will not be zero terminated.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   data = "abcd\x00efgh"
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Stringz.new
 | 
			
		||||
  #   obj.read(data)
 | 
			
		||||
  #   obj.snapshot #=> "abcd"
 | 
			
		||||
  #   obj.num_bytes #=> 5
 | 
			
		||||
  #   obj.to_binary_s #=> "abcd\000"
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Stringz objects accept all the params that BinData::BasePrimitive
 | 
			
		||||
  # does, as well as the following:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:max_length</tt>:: The maximum length of the string including the zero
 | 
			
		||||
  #                        byte.
 | 
			
		||||
  class Stringz < BinData::BasePrimitive
 | 
			
		||||
 | 
			
		||||
    optional_parameters :max_length
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      super(binary_string(val))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      # override to always remove trailing zero bytes
 | 
			
		||||
      result = super
 | 
			
		||||
      trim_and_zero_terminate(result).chomp("\0")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      trim_and_zero_terminate(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      max_length = eval_parameter(:max_length)
 | 
			
		||||
      str = ""
 | 
			
		||||
      i = 0
 | 
			
		||||
      ch = nil
 | 
			
		||||
 | 
			
		||||
      # read until zero byte or we have read in the max number of bytes
 | 
			
		||||
      while ch != "\0" && i != max_length
 | 
			
		||||
        ch = io.readbytes(1)
 | 
			
		||||
        str << ch
 | 
			
		||||
        i += 1
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      trim_and_zero_terminate(str)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      ""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trim_and_zero_terminate(str)
 | 
			
		||||
      result = binary_string(str)
 | 
			
		||||
      truncate_after_first_zero_byte!(result)
 | 
			
		||||
      trim_to!(result, eval_parameter(:max_length))
 | 
			
		||||
      append_zero_byte_if_needed!(result)
 | 
			
		||||
      result
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def truncate_after_first_zero_byte!(str)
 | 
			
		||||
      str.sub!(/([^\0]*\0).*/, '\1')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trim_to!(str, max_length = nil)
 | 
			
		||||
      if max_length
 | 
			
		||||
        max_length = 1 if max_length < 1
 | 
			
		||||
        str.slice!(max_length..-1)
 | 
			
		||||
        if str.length == max_length && str[-1, 1] != "\0"
 | 
			
		||||
          str[-1, 1] = "\0"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def append_zero_byte_if_needed!(str)
 | 
			
		||||
      if str.length == 0 || str[-1, 1] != "\0"
 | 
			
		||||
        str << "\0"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										415
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/struct.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										415
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/struct.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,415 @@
 | 
			
		||||
require 'bindata/base'
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
 | 
			
		||||
  class Base
 | 
			
		||||
    optional_parameter :onlyif, :byte_align  # Used by Struct
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # A Struct is an ordered collection of named data objects.
 | 
			
		||||
  #
 | 
			
		||||
  #    require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #    class Tuple < BinData::Record
 | 
			
		||||
  #      int8  :x
 | 
			
		||||
  #      int8  :y
 | 
			
		||||
  #      int8  :z
 | 
			
		||||
  #    end
 | 
			
		||||
  #
 | 
			
		||||
  #    obj = BinData::Struct.new(hide: :a,
 | 
			
		||||
  #                              fields: [ [:int32le, :a],
 | 
			
		||||
  #                                        [:int16le, :b],
 | 
			
		||||
  #                                        [:tuple, :s] ])
 | 
			
		||||
  #    obj.field_names   =># [:b, :s]
 | 
			
		||||
  #
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:fields</tt>::   An array specifying the fields for this struct.
 | 
			
		||||
  #                      Each element of the array is of the form [type, name,
 | 
			
		||||
  #                      params].  Type is a symbol representing a registered
 | 
			
		||||
  #                      type.  Name is the name of this field.  Params is an
 | 
			
		||||
  #                      optional hash of parameters to pass to this field
 | 
			
		||||
  #                      when instantiating it.  If name is "" or nil, then
 | 
			
		||||
  #                      that field is anonymous and behaves as a hidden field.
 | 
			
		||||
  # <tt>:hide</tt>::     A list of the names of fields that are to be hidden
 | 
			
		||||
  #                      from the outside world.  Hidden fields don't appear
 | 
			
		||||
  #                      in #snapshot or #field_names but are still accessible
 | 
			
		||||
  #                      by name.
 | 
			
		||||
  # <tt>:endian</tt>::   Either :little or :big.  This specifies the default
 | 
			
		||||
  #                      endian of any numerics in this struct, or in any
 | 
			
		||||
  #                      nested data objects.
 | 
			
		||||
  # <tt>:search_prefix</tt>::  Allows abbreviated type names.  If a type is
 | 
			
		||||
  #                            unrecognised, then each prefix is applied until
 | 
			
		||||
  #                            a match is found.
 | 
			
		||||
  #
 | 
			
		||||
  # == Field Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Fields may have have extra parameters as listed below:
 | 
			
		||||
  #
 | 
			
		||||
  # [<tt>:onlyif</tt>]     Used to indicate a data object is optional.
 | 
			
		||||
  #                        if +false+, this object will not be included in any
 | 
			
		||||
  #                        calls to #read, #write, #num_bytes or #snapshot.
 | 
			
		||||
  # [<tt>:byte_align</tt>] This field's rel_offset must be a multiple of
 | 
			
		||||
  #                        <tt>:byte_align</tt>.
 | 
			
		||||
  class Struct < BinData::Base
 | 
			
		||||
    arg_processor :struct
 | 
			
		||||
 | 
			
		||||
    mandatory_parameter :fields
 | 
			
		||||
    optional_parameters :endian, :search_prefix, :hide
 | 
			
		||||
 | 
			
		||||
    # These reserved words may not be used as field names
 | 
			
		||||
    RESERVED =
 | 
			
		||||
      Hash[*
 | 
			
		||||
        (Hash.instance_methods +
 | 
			
		||||
         %w{alias and begin break case class def defined do else elsif
 | 
			
		||||
            end ensure false for if in module next nil not or redo
 | 
			
		||||
            rescue retry return self super then true undef unless until
 | 
			
		||||
            when while yield} +
 | 
			
		||||
         %w{array element index value} +
 | 
			
		||||
         %w{type initial_length read_until} +
 | 
			
		||||
         %w{fields endian search_prefix hide only_if byte_align} +
 | 
			
		||||
         %w{choices selection copy_on_change} +
 | 
			
		||||
         %w{read_abs_offset struct_params}).collect(&:to_sym).
 | 
			
		||||
         uniq.collect { |key| [key, true] }.flatten
 | 
			
		||||
      ]
 | 
			
		||||
 | 
			
		||||
    def initialize_shared_instance
 | 
			
		||||
      fields = get_parameter(:fields)
 | 
			
		||||
      @field_names = fields.field_names.freeze
 | 
			
		||||
      extend ByteAlignPlugin if fields.any_field_has_parameter?(:byte_align)
 | 
			
		||||
      define_field_accessors
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def initialize_instance
 | 
			
		||||
      @field_objs = []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear #:nodoc:
 | 
			
		||||
      @field_objs.each { |f| f.clear unless f.nil? }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def clear? #:nodoc:
 | 
			
		||||
      @field_objs.all? { |f| f.nil? || f.clear? }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign(val)
 | 
			
		||||
      clear
 | 
			
		||||
      assign_fields(val)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def snapshot
 | 
			
		||||
      snapshot = Snapshot.new
 | 
			
		||||
      field_names.each do |name|
 | 
			
		||||
        obj = find_obj_for_name(name)
 | 
			
		||||
        snapshot[name] = obj.snapshot if include_obj?(obj)
 | 
			
		||||
      end
 | 
			
		||||
      snapshot
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns a list of the names of all fields accessible through this
 | 
			
		||||
    # object.  +include_hidden+ specifies whether to include hidden names
 | 
			
		||||
    # in the listing.
 | 
			
		||||
    def field_names(include_hidden = false)
 | 
			
		||||
      if include_hidden
 | 
			
		||||
        @field_names.compact
 | 
			
		||||
      else
 | 
			
		||||
        hidden = get_parameter(:hide) || []
 | 
			
		||||
        @field_names.compact - hidden
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def debug_name_of(child) #:nodoc:
 | 
			
		||||
      field_name = @field_names[find_index_of(child)]
 | 
			
		||||
      "#{debug_name}.#{field_name}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def offset_of(child) #:nodoc:
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      sum = sum_num_bytes_below_index(find_index_of(child))
 | 
			
		||||
      child.bit_aligned? ? sum.floor : sum.ceil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read(io) #:nodoc:
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      @field_objs.each { |f| f.do_read(io) if include_obj?(f) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io) #:nodoc
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      @field_objs.each { |f| f.do_write(io) if include_obj?(f) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes #:nodoc:
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      sum_num_bytes_for_all_fields
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def [](key)
 | 
			
		||||
      find_obj_for_name(key)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def []=(key, value)
 | 
			
		||||
      obj = find_obj_for_name(key)
 | 
			
		||||
      if obj
 | 
			
		||||
        obj.assign(value)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def key?(key)
 | 
			
		||||
      @field_names.index(base_field_name(key))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def each_pair
 | 
			
		||||
      @field_names.compact.each do |name|
 | 
			
		||||
        yield [name, find_obj_for_name(name)]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def define_field_accessors
 | 
			
		||||
      get_parameter(:fields).each_with_index do |field, i|
 | 
			
		||||
        name = field.name_as_sym
 | 
			
		||||
        define_field_accessors_for(name, i) if name
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def define_field_accessors_for(name, index)
 | 
			
		||||
      define_singleton_method(name) do
 | 
			
		||||
        instantiate_obj_at(index) if @field_objs[index].nil?
 | 
			
		||||
        @field_objs[index]
 | 
			
		||||
      end
 | 
			
		||||
      define_singleton_method("#{name}=") do |*vals|
 | 
			
		||||
        instantiate_obj_at(index) if @field_objs[index].nil?
 | 
			
		||||
        @field_objs[index].assign(*vals)
 | 
			
		||||
      end
 | 
			
		||||
      define_singleton_method("#{name}?") do
 | 
			
		||||
        instantiate_obj_at(index) if @field_objs[index].nil?
 | 
			
		||||
        include_obj?(@field_objs[index])
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def find_index_of(obj)
 | 
			
		||||
      @field_objs.index { |el| el.equal?(obj) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def find_obj_for_name(name)
 | 
			
		||||
      index = @field_names.index(base_field_name(name))
 | 
			
		||||
      if index
 | 
			
		||||
        instantiate_obj_at(index)
 | 
			
		||||
        @field_objs[index]
 | 
			
		||||
      else
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def base_field_name(name)
 | 
			
		||||
      name.to_s.sub(/(=|\?)\z/, "").to_sym
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def instantiate_all_objs
 | 
			
		||||
      @field_names.each_index { |i| instantiate_obj_at(i) }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def instantiate_obj_at(index)
 | 
			
		||||
      if @field_objs[index].nil?
 | 
			
		||||
        field = get_parameter(:fields)[index]
 | 
			
		||||
        @field_objs[index] = field.instantiate(nil, self)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def assign_fields(val)
 | 
			
		||||
      src = as_stringified_hash(val)
 | 
			
		||||
 | 
			
		||||
      @field_names.compact.each do |name|
 | 
			
		||||
        obj = find_obj_for_name(name)
 | 
			
		||||
        if obj && src.key?(name)
 | 
			
		||||
          obj.assign(src[name])
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def as_stringified_hash(val)
 | 
			
		||||
      if BinData::Struct === val
 | 
			
		||||
        val
 | 
			
		||||
      elsif val.nil?
 | 
			
		||||
        {}
 | 
			
		||||
      else
 | 
			
		||||
        hash = Snapshot.new
 | 
			
		||||
        val.each_pair { |k,v| hash[k] = v }
 | 
			
		||||
        hash
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sum_num_bytes_for_all_fields
 | 
			
		||||
      sum_num_bytes_below_index(@field_objs.length)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sum_num_bytes_below_index(index)
 | 
			
		||||
      (0...index).inject(0) do |sum, i|
 | 
			
		||||
        obj = @field_objs[i]
 | 
			
		||||
        if include_obj?(obj)
 | 
			
		||||
          nbytes = obj.do_num_bytes
 | 
			
		||||
          (nbytes.is_a?(Integer) ? sum.ceil : sum) + nbytes
 | 
			
		||||
        else
 | 
			
		||||
          sum
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def include_obj?(obj)
 | 
			
		||||
      !obj.has_parameter?(:onlyif) || obj.eval_parameter(:onlyif)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # A hash that can be accessed via attributes.
 | 
			
		||||
    class Snapshot < ::Hash #:nodoc:
 | 
			
		||||
      def []=(key, value)
 | 
			
		||||
        super unless value.nil?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def respond_to?(symbol, include_private = false)
 | 
			
		||||
        key?(symbol) || super
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def method_missing(symbol, *args)
 | 
			
		||||
        key?(symbol) ? self[symbol] : super
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Align fields to a multiple of :byte_align
 | 
			
		||||
  module ByteAlignPlugin
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
      initial_offset = io.offset
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      @field_objs.each do |f|
 | 
			
		||||
        if include_obj?(f)
 | 
			
		||||
          if align_obj?(f)
 | 
			
		||||
            io.seekbytes(bytes_to_align(f, io.offset - initial_offset))
 | 
			
		||||
          end
 | 
			
		||||
          f.do_read(io)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io)
 | 
			
		||||
      initial_offset = io.offset
 | 
			
		||||
      instantiate_all_objs
 | 
			
		||||
      @field_objs.each do |f|
 | 
			
		||||
        if include_obj?(f)
 | 
			
		||||
          if align_obj?(f)
 | 
			
		||||
            io.writebytes("\x00" * bytes_to_align(f, io.offset - initial_offset))
 | 
			
		||||
          end
 | 
			
		||||
          f.do_write(io)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sum_num_bytes_below_index(index)
 | 
			
		||||
      sum = 0
 | 
			
		||||
      (0...@field_objs.length).each do |i|
 | 
			
		||||
        obj = @field_objs[i]
 | 
			
		||||
        if include_obj?(obj)
 | 
			
		||||
          sum = sum.ceil + bytes_to_align(obj, sum.ceil) if align_obj?(obj)
 | 
			
		||||
 | 
			
		||||
          break if i >= index
 | 
			
		||||
 | 
			
		||||
          nbytes = obj.do_num_bytes
 | 
			
		||||
          sum = (nbytes.is_a?(Integer) ? sum.ceil : sum) + nbytes
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      sum
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def bytes_to_align(obj, rel_offset)
 | 
			
		||||
      align = obj.eval_parameter(:byte_align)
 | 
			
		||||
      (align - (rel_offset % align)) % align
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def align_obj?(obj)
 | 
			
		||||
      obj.has_parameter?(:byte_align)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class StructArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params)
 | 
			
		||||
      sanitize_endian(params)
 | 
			
		||||
      sanitize_search_prefix(params)
 | 
			
		||||
      sanitize_fields(obj_class, params)
 | 
			
		||||
      sanitize_hide(params)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #-------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def sanitize_endian(params)
 | 
			
		||||
      params.sanitize_endian(:endian)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_search_prefix(params)
 | 
			
		||||
      params.sanitize(:search_prefix) do |sprefix|
 | 
			
		||||
        search_prefix = []
 | 
			
		||||
        Array(sprefix).each do |prefix|
 | 
			
		||||
          prefix = prefix.to_s.chomp("_")
 | 
			
		||||
          search_prefix << prefix if prefix != ""
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        search_prefix
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_fields(obj_class, params)
 | 
			
		||||
      params.sanitize_fields(:fields) do |fields, sanitized_fields|
 | 
			
		||||
        fields.each do |ftype, fname, fparams|
 | 
			
		||||
          sanitized_fields.add_field(ftype, fname, fparams)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        field_names = sanitized_field_names(sanitized_fields)
 | 
			
		||||
        ensure_field_names_are_valid(obj_class, field_names)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitize_hide(params)
 | 
			
		||||
      params.sanitize(:hide) do |hidden|
 | 
			
		||||
        field_names  = sanitized_field_names(params[:fields])
 | 
			
		||||
        hfield_names = hidden_field_names(hidden)
 | 
			
		||||
 | 
			
		||||
        hfield_names & field_names
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sanitized_field_names(sanitized_fields)
 | 
			
		||||
      sanitized_fields.field_names.compact
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def hidden_field_names(hidden)
 | 
			
		||||
      (hidden || []).collect(&:to_sym)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ensure_field_names_are_valid(obj_class, field_names)
 | 
			
		||||
      reserved_names = BinData::Struct::RESERVED
 | 
			
		||||
 | 
			
		||||
      field_names.each do |name|
 | 
			
		||||
        if obj_class.method_defined?(name)
 | 
			
		||||
          raise NameError.new("Rename field '#{name}' in #{obj_class}, " \
 | 
			
		||||
                              "as it shadows an existing method.", name)
 | 
			
		||||
        end
 | 
			
		||||
        if reserved_names.include?(name)
 | 
			
		||||
          raise NameError.new("Rename field '#{name}' in #{obj_class}, " \
 | 
			
		||||
                              "as it is a reserved name.", name)
 | 
			
		||||
        end
 | 
			
		||||
        if field_names.count(name) != 1
 | 
			
		||||
          raise NameError.new("field '#{name}' in #{obj_class}, " \
 | 
			
		||||
                              "is defined multiple times.", name)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										95
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/trace.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/trace.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  # reference to the current tracer
 | 
			
		||||
  @tracer ||= nil
 | 
			
		||||
 | 
			
		||||
  class Tracer #:nodoc:
 | 
			
		||||
    def initialize(io)
 | 
			
		||||
      @trace_io = io
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trace(msg)
 | 
			
		||||
      @trace_io.puts(msg)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trace_obj(obj_name, val)
 | 
			
		||||
      if val.length > 30
 | 
			
		||||
        val = val.slice(0..30) + "..."
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      trace "#{obj_name} => #{val}"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Turn on trace information when reading a BinData object.
 | 
			
		||||
  # If +block+ is given then the tracing only occurs for that block.
 | 
			
		||||
  # This is useful for debugging a BinData declaration.
 | 
			
		||||
  def trace_reading(io = STDERR)
 | 
			
		||||
    @tracer = Tracer.new(io)
 | 
			
		||||
    [BasePrimitive, Choice].each(&:turn_on_tracing)
 | 
			
		||||
 | 
			
		||||
    if block_given?
 | 
			
		||||
      begin
 | 
			
		||||
        yield
 | 
			
		||||
      ensure
 | 
			
		||||
        [BasePrimitive, Choice].each(&:turn_off_tracing)
 | 
			
		||||
        @tracer = nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def trace_message #:nodoc:
 | 
			
		||||
    yield @tracer if @tracer
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  module_function :trace_reading, :trace_message
 | 
			
		||||
 | 
			
		||||
  class BasePrimitive < BinData::Base
 | 
			
		||||
    class << self
 | 
			
		||||
      def turn_on_tracing
 | 
			
		||||
        alias_method :do_read_without_hook, :do_read
 | 
			
		||||
        alias_method :do_read, :do_read_with_hook
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def turn_off_tracing
 | 
			
		||||
        alias_method :do_read, :do_read_without_hook
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read_with_hook(io)
 | 
			
		||||
      do_read_without_hook(io)
 | 
			
		||||
      trace_value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trace_value
 | 
			
		||||
      BinData.trace_message do |tracer|
 | 
			
		||||
        value_string = _value.inspect
 | 
			
		||||
        tracer.trace_obj(debug_name, value_string)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Choice < BinData::Base
 | 
			
		||||
    class << self
 | 
			
		||||
      def turn_on_tracing
 | 
			
		||||
        alias_method :do_read_without_hook, :do_read
 | 
			
		||||
        alias_method :do_read, :do_read_with_hook
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def turn_off_tracing
 | 
			
		||||
        alias_method :do_read, :do_read_without_hook
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_read_with_hook(io)
 | 
			
		||||
      trace_selection
 | 
			
		||||
      do_read_without_hook(io)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def trace_selection
 | 
			
		||||
      BinData.trace_message do |tracer|
 | 
			
		||||
        selection_string = eval_parameter(:selection).inspect
 | 
			
		||||
        tracer.trace_obj("#{debug_name}-selection-", selection_string)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										62
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/uint8_array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/uint8_array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
require "bindata/base_primitive"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # Uint8Array is a specialised type of array that only contains
 | 
			
		||||
  # bytes (Uint8).  It is a faster and more memory efficient version
 | 
			
		||||
  # of `BinData::Array.new(:type => :uint8)`.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = BinData::Uint8Array.new(initial_length: 5)
 | 
			
		||||
  #   obj.read("abcdefg") #=> [97, 98, 99, 100, 101]
 | 
			
		||||
  #   obj[2] #=> 99
 | 
			
		||||
  #   obj.collect { |x| x.chr }.join #=> "abcde"
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params are:
 | 
			
		||||
  #
 | 
			
		||||
  # <tt>:initial_length</tt>:: The initial length of the array.
 | 
			
		||||
  # <tt>:read_until</tt>::     May only have a value of `:eof`.  This parameter
 | 
			
		||||
  #                            instructs the array to read as much data from
 | 
			
		||||
  #                            the stream as possible.
 | 
			
		||||
  class Uint8Array < BinData::BasePrimitive
 | 
			
		||||
    optional_parameters :initial_length, :read_until
 | 
			
		||||
    mutually_exclusive_parameters :initial_length, :read_until
 | 
			
		||||
    arg_processor :uint8_array
 | 
			
		||||
 | 
			
		||||
    #---------------
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def value_to_binary_string(val)
 | 
			
		||||
      val.pack("C*")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def read_and_return_value(io)
 | 
			
		||||
      if has_parameter?(:initial_length)
 | 
			
		||||
        data = io.readbytes(eval_parameter(:initial_length))
 | 
			
		||||
      else
 | 
			
		||||
        data = io.read_all_bytes
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      data.unpack("C*")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      []
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Uint8ArrayArgProcessor < BaseArgProcessor
 | 
			
		||||
    def sanitize_parameters!(obj_class, params) #:nodoc:
 | 
			
		||||
      # ensure one of :initial_length and :read_until exists
 | 
			
		||||
      unless params.has_at_least_one_of?(:initial_length, :read_until)
 | 
			
		||||
        params[:initial_length] = 0
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      msg = "Parameter :read_until must have a value of :eof"
 | 
			
		||||
      params.sanitize(:read_until) { |val| raise ArgumentError, msg unless val == :eof }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										3
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  VERSION = "2.4.8"
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										47
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/virtual.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/virtual.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
require "bindata/base"
 | 
			
		||||
 | 
			
		||||
module BinData
 | 
			
		||||
  # A virtual field is one that is neither read, written nor occupies space in
 | 
			
		||||
  # the data stream.  It is used to make assertions or as a convenient label
 | 
			
		||||
  # for determining offsets or storing values.
 | 
			
		||||
  #
 | 
			
		||||
  #   require 'bindata'
 | 
			
		||||
  #
 | 
			
		||||
  #   class A < BinData::Record
 | 
			
		||||
  #     string  :a, read_length: 5
 | 
			
		||||
  #     string  :b, read_length: 5
 | 
			
		||||
  #     virtual :c, assert: -> { a == b }
 | 
			
		||||
  #   end
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = A.read("abcdeabcde")
 | 
			
		||||
  #   obj.a #=> "abcde"
 | 
			
		||||
  #   obj.c.offset #=> 10
 | 
			
		||||
  #
 | 
			
		||||
  #   obj = A.read("abcdeABCDE") #=> BinData::ValidityError: assertion failed for obj.c
 | 
			
		||||
  #
 | 
			
		||||
  # == Parameters
 | 
			
		||||
  #
 | 
			
		||||
  # Parameters may be provided at initialisation to control the behaviour of
 | 
			
		||||
  # an object.  These params include those for BinData::Base as well as:
 | 
			
		||||
  #
 | 
			
		||||
  # [<tt>:assert</tt>]    Raise an error when reading or assigning if the value
 | 
			
		||||
  #                       of this evaluated parameter is false.
 | 
			
		||||
  # [<tt>:value</tt>]     The virtual object will always have this value.
 | 
			
		||||
  #
 | 
			
		||||
  class Virtual < BinData::BasePrimitive
 | 
			
		||||
 | 
			
		||||
    def do_read(io)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_write(io)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def do_num_bytes
 | 
			
		||||
      0.0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def sensible_default
 | 
			
		||||
      nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										36
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/warnings.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/bindata-2.4.8/lib/bindata/warnings.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
module BinData
 | 
			
		||||
  class Base
 | 
			
		||||
    # Don't override initialize.  If you are defining a new kind of datatype
 | 
			
		||||
    # (list, array, choice etc) then put your initialization code in
 | 
			
		||||
    # #initialize_instance.  BinData objects might be initialized as prototypes
 | 
			
		||||
    # and your initialization code may not be called.
 | 
			
		||||
    #
 | 
			
		||||
    # If you're subclassing BinData::Record, you are definitely doing the wrong
 | 
			
		||||
    # thing.  Read the documentation on how to use BinData.
 | 
			
		||||
    # http://github.com/dmendel/bindata/wiki/Records
 | 
			
		||||
    alias_method :initialize_without_warning, :initialize
 | 
			
		||||
    def initialize_with_warning(*args)
 | 
			
		||||
      owner = method(:initialize).owner
 | 
			
		||||
      if owner != BinData::Base
 | 
			
		||||
        msg = "Don't override #initialize on #{owner}."
 | 
			
		||||
        if %w(BinData::Base BinData::BasePrimitive).include? self.class.superclass.name
 | 
			
		||||
          msg += "\nrename #initialize to #initialize_instance."
 | 
			
		||||
        end
 | 
			
		||||
        fail msg
 | 
			
		||||
      end
 | 
			
		||||
      initialize_without_warning(*args)
 | 
			
		||||
    end
 | 
			
		||||
    alias initialize initialize_with_warning
 | 
			
		||||
 | 
			
		||||
    def initialize_instance(*args)
 | 
			
		||||
      unless args.empty?
 | 
			
		||||
        fail "#{caller[0]} remove the call to super in #initialize_instance"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Struct
 | 
			
		||||
    # has_key? is deprecated
 | 
			
		||||
    alias has_key? key?
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										11
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/constants'
 | 
			
		||||
require 'elftools/elf_file'
 | 
			
		||||
require 'elftools/version'
 | 
			
		||||
 | 
			
		||||
# The ELF parsing tools!
 | 
			
		||||
# Main entry point is {ELFTools::ELFFile}, see it
 | 
			
		||||
# for more information.
 | 
			
		||||
module ELFTools
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										303
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/constants.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/constants.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,303 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Define constants from elf.h.
 | 
			
		||||
  # Mostly refer from https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
 | 
			
		||||
  # and binutils/elfcpp/elfcpp.h.
 | 
			
		||||
  module Constants
 | 
			
		||||
    # ELF magic header
 | 
			
		||||
    ELFMAG = "\x7FELF"
 | 
			
		||||
 | 
			
		||||
    # Values of `d_un.d_val' in the DT_FLAGS and DT_FLAGS_1 entry.
 | 
			
		||||
    module DF
 | 
			
		||||
      DF_ORIGIN       = 0x00000001 # Object may use DF_ORIGIN
 | 
			
		||||
      DF_SYMBOLIC     = 0x00000002 # Symbol resolutions starts here
 | 
			
		||||
      DF_TEXTREL      = 0x00000004 # Object contains text relocations
 | 
			
		||||
      DF_BIND_NOW     = 0x00000008 # No lazy binding for this object
 | 
			
		||||
      DF_STATIC_TLS   = 0x00000010 # Module uses the static TLS model
 | 
			
		||||
 | 
			
		||||
      DF_1_NOW        = 0x00000001 # Set RTLD_NOW for this object.
 | 
			
		||||
      DF_1_GLOBAL     = 0x00000002 # Set RTLD_GLOBAL for this object.
 | 
			
		||||
      DF_1_GROUP      = 0x00000004 # Set RTLD_GROUP for this object.
 | 
			
		||||
      DF_1_NODELETE   = 0x00000008 # Set RTLD_NODELETE for this object.
 | 
			
		||||
      DF_1_LOADFLTR   = 0x00000010 # Trigger filtee loading at runtime.
 | 
			
		||||
      DF_1_INITFIRST  = 0x00000020 # Set RTLD_INITFIRST for this object
 | 
			
		||||
      DF_1_NOOPEN     = 0x00000040 # Set RTLD_NOOPEN for this object.
 | 
			
		||||
      DF_1_ORIGIN     = 0x00000080 # $ORIGIN must be handled.
 | 
			
		||||
      DF_1_DIRECT     = 0x00000100 # Direct binding enabled.
 | 
			
		||||
      DF_1_TRANS      = 0x00000200 # :nodoc:
 | 
			
		||||
      DF_1_INTERPOSE  = 0x00000400 # Object is used to interpose.
 | 
			
		||||
      DF_1_NODEFLIB   = 0x00000800 # Ignore default lib search path.
 | 
			
		||||
      DF_1_NODUMP     = 0x00001000 # Object can't be dldump'ed.
 | 
			
		||||
      DF_1_CONFALT    = 0x00002000 # Configuration alternative created.
 | 
			
		||||
      DF_1_ENDFILTEE  = 0x00004000 # Filtee terminates filters search.
 | 
			
		||||
      DF_1_DISPRELDNE = 0x00008000 # Disp reloc applied at build time.
 | 
			
		||||
      DF_1_DISPRELPND = 0x00010000 # Disp reloc applied at run-time.
 | 
			
		||||
      DF_1_NODIRECT   = 0x00020000 # Object has no-direct binding.
 | 
			
		||||
      DF_1_IGNMULDEF  = 0x00040000 # :nodoc:
 | 
			
		||||
      DF_1_NOKSYMS    = 0x00080000 # :nodoc:
 | 
			
		||||
      DF_1_NOHDR      = 0x00100000 # :nodoc:
 | 
			
		||||
      DF_1_EDITED     = 0x00200000 # Object is modified after built.
 | 
			
		||||
      DF_1_NORELOC    = 0x00400000 # :nodoc:
 | 
			
		||||
      DF_1_SYMINTPOSE = 0x00800000 # Object has individual interposers.
 | 
			
		||||
      DF_1_GLOBAUDIT  = 0x01000000 # Global auditing required.
 | 
			
		||||
      DF_1_SINGLETON  = 0x02000000 # Singleton symbols are used.
 | 
			
		||||
    end
 | 
			
		||||
    include DF
 | 
			
		||||
 | 
			
		||||
    # Dynamic table types, records in +d_tag+.
 | 
			
		||||
    module DT
 | 
			
		||||
      DT_NULL         = 0 # marks the end of the _DYNAMIC array
 | 
			
		||||
      DT_NEEDED       = 1 # libraries need to be linked by loader
 | 
			
		||||
      DT_PLTRELSZ     = 2 # total size of relocation entries
 | 
			
		||||
      DT_PLTGOT       = 3 # address of procedure linkage table or global offset table
 | 
			
		||||
      DT_HASH         = 4 # address of symbol hash table
 | 
			
		||||
      DT_STRTAB       = 5 # address of string table
 | 
			
		||||
      DT_SYMTAB       = 6 # address of symbol table
 | 
			
		||||
      DT_RELA         = 7 # address of a relocation table
 | 
			
		||||
      DT_RELASZ       = 8 # total size of the {DT_RELA} table
 | 
			
		||||
      DT_RELAENT      = 9 # size of each entry in the {DT_RELA} table
 | 
			
		||||
      DT_STRSZ        = 10 # total size of {DT_STRTAB}
 | 
			
		||||
      DT_SYMENT       = 11 # size of each entry in {DT_SYMTAB}
 | 
			
		||||
      DT_INIT         = 12 # where the initialization function is
 | 
			
		||||
      DT_FINI         = 13 # where the termination function is
 | 
			
		||||
      DT_SONAME       = 14 # the shared object name
 | 
			
		||||
      DT_RPATH        = 15 # has been superseded by {DT_RUNPATH}
 | 
			
		||||
      DT_SYMBOLIC     = 16 # has been superseded by the DF_SYMBOLIC flag
 | 
			
		||||
      DT_REL          = 17 # similar to {DT_RELA}
 | 
			
		||||
      DT_RELSZ        = 18 # total size of the {DT_REL} table
 | 
			
		||||
      DT_RELENT       = 19 # size of each entry in the {DT_REL} table
 | 
			
		||||
      DT_PLTREL       = 20 # type of relocation entry, either {DT_REL} or {DT_RELA}
 | 
			
		||||
      DT_DEBUG        = 21 # for debugging
 | 
			
		||||
      DT_TEXTREL      = 22 # has been superseded by the DF_TEXTREL flag
 | 
			
		||||
      DT_JMPREL       = 23 # address of relocation entries that are associated solely with the procedure linkage table
 | 
			
		||||
      DT_BIND_NOW     = 24 # if the loader needs to do relocate now, superseded by the DF_BIND_NOW flag
 | 
			
		||||
      DT_INIT_ARRAY   = 25 # address init array
 | 
			
		||||
      DT_FINI_ARRAY   = 26 # address of fini array
 | 
			
		||||
      DT_INIT_ARRAYSZ = 27 # total size of init array
 | 
			
		||||
      DT_FINI_ARRAYSZ = 28 # total size of fini array
 | 
			
		||||
      DT_RUNPATH      = 29 # path of libraries for searching
 | 
			
		||||
      DT_FLAGS        = 30 # flags
 | 
			
		||||
      DT_ENCODING     = 32 # just a lower bound
 | 
			
		||||
      # Values between {DT_LOOS} and {DT_HIOS} are reserved for operating system-specific semantics.
 | 
			
		||||
      DT_LOOS         = 0x6000000d
 | 
			
		||||
      DT_HIOS         = 0x6ffff000 # see {DT_LOOS}
 | 
			
		||||
      # Values between {DT_VALRNGLO} and {DT_VALRNGHI} use the +d_un.d_val+ field of the dynamic structure.
 | 
			
		||||
      DT_VALRNGLO     = 0x6ffffd00
 | 
			
		||||
      DT_VALRNGHI     = 0x6ffffdff # see {DT_VALRNGLO}
 | 
			
		||||
      # Values between {DT_ADDRRNGLO} and {DT_ADDRRNGHI} use the +d_un.d_ptr+ field of the dynamic structure.
 | 
			
		||||
      DT_ADDRRNGLO    = 0x6ffffe00
 | 
			
		||||
      DT_GNU_HASH     = 0x6ffffef5 # the gnu hash
 | 
			
		||||
      DT_ADDRRNGHI    = 0x6ffffeff # see {DT_ADDRRNGLO}
 | 
			
		||||
      DT_RELACOUNT    = 0x6ffffff9 # relative relocation count
 | 
			
		||||
      DT_RELCOUNT     = 0x6ffffffa # relative relocation count
 | 
			
		||||
      DT_FLAGS_1      = 0x6ffffffb # flags
 | 
			
		||||
      DT_VERDEF       = 0x6ffffffc # address of version definition table
 | 
			
		||||
      DT_VERDEFNUM    = 0x6ffffffd # number of entries in {DT_VERDEF}
 | 
			
		||||
      DT_VERNEED      = 0x6ffffffe # address of version dependency table
 | 
			
		||||
      DT_VERNEEDNUM   = 0x6fffffff # number of entries in {DT_VERNEED}
 | 
			
		||||
      # Values between {DT_LOPROC} and {DT_HIPROC} are reserved for processor-specific semantics.
 | 
			
		||||
      DT_LOPROC       = 0x70000000
 | 
			
		||||
      DT_HIPROC       = 0x7fffffff # see {DT_LOPROC}
 | 
			
		||||
    end
 | 
			
		||||
    include DT
 | 
			
		||||
 | 
			
		||||
    # These constants define the various ELF target machines.
 | 
			
		||||
    module EM
 | 
			
		||||
      EM_NONE           = 0      # none
 | 
			
		||||
      EM_M32            = 1      # AT&T WE 32100
 | 
			
		||||
      EM_SPARC          = 2      # SPARC
 | 
			
		||||
      EM_386            = 3      # Intel 80386
 | 
			
		||||
      EM_68K            = 4      # Motorola 68000
 | 
			
		||||
      EM_88K            = 5      # Motorola 88000
 | 
			
		||||
      EM_486            = 6      # Intel 80486
 | 
			
		||||
      EM_860            = 7      # Intel 80860
 | 
			
		||||
      EM_MIPS           = 8      # MIPS R3000 (officially, big-endian only)
 | 
			
		||||
 | 
			
		||||
      # Next two are historical and binaries and
 | 
			
		||||
      # modules of these types will be rejected by Linux.
 | 
			
		||||
      EM_MIPS_RS3_LE    = 10     # MIPS R3000 little-endian
 | 
			
		||||
      EM_MIPS_RS4_BE    = 10     # MIPS R4000 big-endian
 | 
			
		||||
 | 
			
		||||
      EM_PARISC         = 15     # HPPA
 | 
			
		||||
      EM_SPARC32PLUS    = 18     # Sun's "v8plus"
 | 
			
		||||
      EM_PPC            = 20     # PowerPC
 | 
			
		||||
      EM_PPC64          = 21     # PowerPC64
 | 
			
		||||
      EM_SPU            = 23     # Cell BE SPU
 | 
			
		||||
      EM_ARM            = 40     # ARM 32 bit
 | 
			
		||||
      EM_SH             = 42     # SuperH
 | 
			
		||||
      EM_SPARCV9        = 43     # SPARC v9 64-bit
 | 
			
		||||
      EM_H8_300         = 46     # Renesas H8/300
 | 
			
		||||
      EM_IA_64          = 50     # HP/Intel IA-64
 | 
			
		||||
      EM_X86_64         = 62     # AMD x86-64
 | 
			
		||||
      EM_S390           = 22     # IBM S/390
 | 
			
		||||
      EM_CRIS           = 76     # Axis Communications 32-bit embedded processor
 | 
			
		||||
      EM_M32R           = 88     # Renesas M32R
 | 
			
		||||
      EM_MN10300        = 89     # Panasonic/MEI MN10300, AM33
 | 
			
		||||
      EM_OPENRISC       = 92     # OpenRISC 32-bit embedded processor
 | 
			
		||||
      EM_BLACKFIN       = 106    # ADI Blackfin Processor
 | 
			
		||||
      EM_ALTERA_NIOS2   = 113    # Altera Nios II soft-core processor
 | 
			
		||||
      EM_TI_C6000       = 140    # TI C6X DSPs
 | 
			
		||||
      EM_AARCH64        = 183    # ARM 64 bit
 | 
			
		||||
      EM_TILEPRO        = 188    # Tilera TILEPro
 | 
			
		||||
      EM_MICROBLAZE     = 189    # Xilinx MicroBlaze
 | 
			
		||||
      EM_TILEGX         = 191    # Tilera TILE-Gx
 | 
			
		||||
      EM_BPF            = 247    # Linux BPF - in-kernel virtual machine
 | 
			
		||||
      EM_FRV            = 0x5441 # Fujitsu FR-V
 | 
			
		||||
      EM_AVR32          = 0x18ad # Atmel AVR32
 | 
			
		||||
 | 
			
		||||
      # This is an interim value that we will use until the committee comes up with a final number.
 | 
			
		||||
      EM_ALPHA          = 0x9026
 | 
			
		||||
 | 
			
		||||
      # Bogus old m32r magic number, used by old tools.
 | 
			
		||||
      EM_CYGNUS_M32R    = 0x9041
 | 
			
		||||
      # This is the old interim value for S/390 architecture
 | 
			
		||||
      EM_S390_OLD       = 0xA390
 | 
			
		||||
      # Also Panasonic/MEI MN10300, AM33
 | 
			
		||||
      EM_CYGNUS_MN10300 = 0xbeef
 | 
			
		||||
 | 
			
		||||
      # Return the architecture name according to +val+.
 | 
			
		||||
      # Used by {ELFTools::ELFFile#machine}.
 | 
			
		||||
      #
 | 
			
		||||
      # Only supports famous archs.
 | 
			
		||||
      # @param [Integer] val Value of +e_machine+.
 | 
			
		||||
      # @return [String]
 | 
			
		||||
      #   Name of architecture.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   mapping(3)
 | 
			
		||||
      #   #=> 'Intel 80386'
 | 
			
		||||
      #   mapping(6)
 | 
			
		||||
      #   #=> 'Intel 80386'
 | 
			
		||||
      #   mapping(62)
 | 
			
		||||
      #   #=> 'Advanced Micro Devices X86-64'
 | 
			
		||||
      #   mapping(1337)
 | 
			
		||||
      #   #=> '<unknown>: 0x539'
 | 
			
		||||
      def self.mapping(val)
 | 
			
		||||
        case val
 | 
			
		||||
        when EM_NONE then 'None'
 | 
			
		||||
        when EM_386, EM_486 then 'Intel 80386'
 | 
			
		||||
        when EM_860 then 'Intel 80860'
 | 
			
		||||
        when EM_MIPS then 'MIPS R3000'
 | 
			
		||||
        when EM_PPC then 'PowerPC'
 | 
			
		||||
        when EM_PPC64 then 'PowerPC64'
 | 
			
		||||
        when EM_ARM then 'ARM'
 | 
			
		||||
        when EM_IA_64 then 'Intel IA-64'
 | 
			
		||||
        when EM_AARCH64 then 'AArch64'
 | 
			
		||||
        when EM_X86_64 then 'Advanced Micro Devices X86-64'
 | 
			
		||||
        else format('<unknown>: 0x%x', val)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    include EM
 | 
			
		||||
 | 
			
		||||
    # This module defines elf file types.
 | 
			
		||||
    module ET
 | 
			
		||||
      ET_NONE = 0 # no file type
 | 
			
		||||
      ET_REL  = 1 # relocatable file
 | 
			
		||||
      ET_EXEC = 2 # executable file
 | 
			
		||||
      ET_DYN  = 3 # shared object
 | 
			
		||||
      ET_CORE = 4 # core file
 | 
			
		||||
      # Return the type name according to +e_type+ in ELF file header.
 | 
			
		||||
      # @return [String] Type in string format.
 | 
			
		||||
      def self.mapping(type)
 | 
			
		||||
        case type
 | 
			
		||||
        when Constants::ET_NONE then 'NONE'
 | 
			
		||||
        when Constants::ET_REL then 'REL'
 | 
			
		||||
        when Constants::ET_EXEC then 'EXEC'
 | 
			
		||||
        when Constants::ET_DYN then 'DYN'
 | 
			
		||||
        when Constants::ET_CORE then 'CORE'
 | 
			
		||||
        else '<unknown>'
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    include ET
 | 
			
		||||
 | 
			
		||||
    # Program header types, records in +p_type+.
 | 
			
		||||
    module PT
 | 
			
		||||
      PT_NULL         = 0          # null segment
 | 
			
		||||
      PT_LOAD         = 1          # segment to be load
 | 
			
		||||
      PT_DYNAMIC      = 2          # dynamic tags
 | 
			
		||||
      PT_INTERP       = 3          # interpreter, same as .interp section
 | 
			
		||||
      PT_NOTE         = 4          # same as .note* section
 | 
			
		||||
      PT_SHLIB        = 5          # reserved
 | 
			
		||||
      PT_PHDR         = 6          # where program header starts
 | 
			
		||||
      PT_TLS          = 7          # thread local storage segment
 | 
			
		||||
      PT_LOOS         = 0x60000000 # OS-specific
 | 
			
		||||
      PT_HIOS         = 0x6fffffff # OS-specific
 | 
			
		||||
      # Values between {PT_LOPROC} and {PT_HIPROC} are reserved for processor-specific semantics.
 | 
			
		||||
      PT_LOPROC       = 0x70000000
 | 
			
		||||
      PT_HIPROC       = 0x7fffffff # see {PT_LOPROC}
 | 
			
		||||
      PT_GNU_EH_FRAME = 0x6474e550 # for exception handler
 | 
			
		||||
      PT_GNU_STACK    = 0x6474e551 # permission of stack
 | 
			
		||||
      PT_GNU_RELRO    = 0x6474e552 # read only after relocation
 | 
			
		||||
    end
 | 
			
		||||
    include PT
 | 
			
		||||
 | 
			
		||||
    # Section header types, records in +sh_type+.
 | 
			
		||||
    module SHT
 | 
			
		||||
      SHT_NULL     = 0 # null section
 | 
			
		||||
      SHT_PROGBITS = 1 # information defined by program itself
 | 
			
		||||
      SHT_SYMTAB   = 2 # symbol table section
 | 
			
		||||
      SHT_STRTAB   = 3 # string table section
 | 
			
		||||
      SHT_RELA     = 4 # relocation with addends
 | 
			
		||||
      SHT_HASH     = 5 # symbol hash table
 | 
			
		||||
      SHT_DYNAMIC  = 6 # information of dynamic linking
 | 
			
		||||
      SHT_NOTE     = 7 # note section
 | 
			
		||||
      SHT_NOBITS   = 8 # section occupies no space
 | 
			
		||||
      SHT_REL      = 9 # relocation
 | 
			
		||||
      SHT_SHLIB    = 10 # reserved
 | 
			
		||||
      SHT_DYNSYM   = 11 # symbols for dynamic
 | 
			
		||||
      # Values between {SHT_LOPROC} and {SHT_HIPROC} are reserved for processor-specific semantics.
 | 
			
		||||
      SHT_LOPROC   = 0x70000000
 | 
			
		||||
      SHT_HIPROC   = 0x7fffffff # see {SHT_LOPROC}
 | 
			
		||||
      # Values between {SHT_LOUSER} and {SHT_HIUSER} are reserved for application programs.
 | 
			
		||||
      SHT_LOUSER   = 0x80000000
 | 
			
		||||
      SHT_HIUSER   = 0xffffffff # see {SHT_LOUSER}
 | 
			
		||||
    end
 | 
			
		||||
    include SHT
 | 
			
		||||
 | 
			
		||||
    # Symbol binding from Sym st_info field.
 | 
			
		||||
    module STB
 | 
			
		||||
      STB_LOCAL      = 0 # Local symbol
 | 
			
		||||
      STB_GLOBAL     = 1 # Global symbol
 | 
			
		||||
      STB_WEAK       = 2 # Weak symbol
 | 
			
		||||
      STB_NUM        = 3 # Number of defined types.
 | 
			
		||||
      STB_LOOS       = 10 # Start of OS-specific
 | 
			
		||||
      STB_GNU_UNIQUE = 10 # Unique symbol.
 | 
			
		||||
      STB_HIOS       = 12 # End of OS-specific
 | 
			
		||||
      STB_LOPROC     = 13 # Start of processor-specific
 | 
			
		||||
      STB_HIPROC     = 15 # End of processor-specific
 | 
			
		||||
    end
 | 
			
		||||
    include STB
 | 
			
		||||
 | 
			
		||||
    # Symbol types from Sym st_info field.
 | 
			
		||||
    module STT
 | 
			
		||||
      STT_NOTYPE         = 0 # Symbol type is unspecified
 | 
			
		||||
      STT_OBJECT         = 1 # Symbol is a data object
 | 
			
		||||
      STT_FUNC           = 2 # Symbol is a code object
 | 
			
		||||
      STT_SECTION        = 3 # Symbol associated with a section
 | 
			
		||||
      STT_FILE           = 4 # Symbol's name is file name
 | 
			
		||||
      STT_COMMON         = 5 # Symbol is a common data object
 | 
			
		||||
      STT_TLS            = 6 # Symbol is thread-local data object
 | 
			
		||||
      STT_NUM            = 7 # Number of defined types.
 | 
			
		||||
 | 
			
		||||
      # GNU extension: symbol value points to a function which is called
 | 
			
		||||
      # at runtime to determine the final value of the symbol.
 | 
			
		||||
      STT_GNU_IFUNC      = 10
 | 
			
		||||
 | 
			
		||||
      STT_LOOS           = 10 # Start of OS-specific
 | 
			
		||||
      STT_HIOS           = 12 # End of OS-specific
 | 
			
		||||
      STT_LOPROC         = 13 # Start of processor-specific
 | 
			
		||||
      STT_HIPROC         = 15 # End of processor-specific
 | 
			
		||||
 | 
			
		||||
      # The section type that must be used for register symbols on
 | 
			
		||||
      # Sparc. These symbols initialize a global register.
 | 
			
		||||
      STT_SPARC_REGISTER = 13
 | 
			
		||||
 | 
			
		||||
      # ARM: a THUMB function. This is not defined in ARM ELF Specification but
 | 
			
		||||
      # used by the GNU tool-chain.
 | 
			
		||||
      STT_ARM_TFUNC      = 13
 | 
			
		||||
    end
 | 
			
		||||
    include STT
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										178
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/dynamic.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/dynamic.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,178 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Define common methods for dynamic sections and dynamic segments.
 | 
			
		||||
  #
 | 
			
		||||
  # @note
 | 
			
		||||
  #   This module can only be included by {ELFTools::Sections::DynamicSection}
 | 
			
		||||
  #   and {ELFTools::Segments::DynamicSegment} because methods here assume some
 | 
			
		||||
  #   attributes exist.
 | 
			
		||||
  module Dynamic
 | 
			
		||||
    # Iterate all tags.
 | 
			
		||||
    #
 | 
			
		||||
    # @note
 | 
			
		||||
    #   This method assume the following methods already exist:
 | 
			
		||||
    #     header
 | 
			
		||||
    #     tag_start
 | 
			
		||||
    # @yieldparam [ELFTools::Dynamic::Tag] tag
 | 
			
		||||
    # @return [Enumerator<ELFTools::Dynamic::Tag>, Array<ELFTools::Dynamic::Tag>]
 | 
			
		||||
    #   If block is not given, an enumerator will be returned.
 | 
			
		||||
    #   Otherwise, return array of tags.
 | 
			
		||||
    def each_tags(&block)
 | 
			
		||||
      return enum_for(:each_tags) unless block_given?
 | 
			
		||||
 | 
			
		||||
      arr = []
 | 
			
		||||
      0.step do |i|
 | 
			
		||||
        tag = tag_at(i).tap(&block)
 | 
			
		||||
        arr << tag
 | 
			
		||||
        break if tag.header.d_tag == ELFTools::Constants::DT_NULL
 | 
			
		||||
      end
 | 
			
		||||
      arr
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Use {#tags} to get all tags.
 | 
			
		||||
    # @return [Array<ELFTools::Dynamic::Tag>]
 | 
			
		||||
    #   Array of tags.
 | 
			
		||||
    def tags
 | 
			
		||||
      @tags ||= each_tags.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get a tag of specific type.
 | 
			
		||||
    # @param [Integer, Symbol, String] type
 | 
			
		||||
    #   Constant value, symbol, or string of type
 | 
			
		||||
    #   is acceptable. See examples for more information.
 | 
			
		||||
    # @return [ELFTools::Dynamic::Tag] The desired tag.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   dynamic = elf.segment_by_type(:dynamic)
 | 
			
		||||
    #   # type as integer
 | 
			
		||||
    #   dynamic.tag_by_type(0) # the null tag
 | 
			
		||||
    #   #=>  #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
 | 
			
		||||
    #   dynamic.tag_by_type(ELFTools::Constants::DT_NULL)
 | 
			
		||||
    #   #=>  #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
 | 
			
		||||
    #
 | 
			
		||||
    #   # symbol
 | 
			
		||||
    #   dynamic.tag_by_type(:null)
 | 
			
		||||
    #   #=>  #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
 | 
			
		||||
    #   dynamic.tag_by_type(:pltgot)
 | 
			
		||||
    #   #=> #<ELFTools::Dynamic::Tag:0x0055d3d2d91b28 @header={:d_tag=>3, :d_val=>6295552}>
 | 
			
		||||
    #
 | 
			
		||||
    #   # string
 | 
			
		||||
    #   dynamic.tag_by_type('null')
 | 
			
		||||
    #   #=>  #<ELFTools::Dynamic::Tag:0x0055b5a5ecad28 @header={:d_tag=>0, :d_val=>0}>
 | 
			
		||||
    #   dynamic.tag_by_type('DT_PLTGOT')
 | 
			
		||||
    #   #=> #<ELFTools::Dynamic::Tag:0x0055d3d2d91b28 @header={:d_tag=>3, :d_val=>6295552}>
 | 
			
		||||
    def tag_by_type(type)
 | 
			
		||||
      type = Util.to_constant(Constants::DT, type)
 | 
			
		||||
      each_tags.find { |tag| tag.header.d_tag == type }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get tags of specific type.
 | 
			
		||||
    # @param [Integer, Symbol, String] type
 | 
			
		||||
    #   Constant value, symbol, or string of type
 | 
			
		||||
    #   is acceptable. See examples for more information.
 | 
			
		||||
    # @return [Array<ELFTools::Dynamic::Tag>] The desired tags.
 | 
			
		||||
    #
 | 
			
		||||
    # @see #tag_by_type
 | 
			
		||||
    def tags_by_type(type)
 | 
			
		||||
      type = Util.to_constant(Constants::DT, type)
 | 
			
		||||
      each_tags.select { |tag| tag.header.d_tag == type }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the +n+-th tag.
 | 
			
		||||
    #
 | 
			
		||||
    # Tags are lazy loaded.
 | 
			
		||||
    # @note
 | 
			
		||||
    #   This method assume the following methods already exist:
 | 
			
		||||
    #     header
 | 
			
		||||
    #     tag_start
 | 
			
		||||
    # @note
 | 
			
		||||
    #   We cannot do bound checking of +n+ here since the only way to get size
 | 
			
		||||
    #   of tags is calling +tags.size+.
 | 
			
		||||
    # @param [Integer] n The index.
 | 
			
		||||
    # @return [ELFTools::Dynamic::Tag] The desired tag.
 | 
			
		||||
    def tag_at(n)
 | 
			
		||||
      return if n.negative?
 | 
			
		||||
 | 
			
		||||
      @tag_at_map ||= {}
 | 
			
		||||
      return @tag_at_map[n] if @tag_at_map[n]
 | 
			
		||||
 | 
			
		||||
      dyn = Structs::ELF_Dyn.new(endian: endian)
 | 
			
		||||
      dyn.elf_class = header.elf_class
 | 
			
		||||
      stream.pos = tag_start + n * dyn.num_bytes
 | 
			
		||||
      dyn.offset = stream.pos
 | 
			
		||||
      @tag_at_map[n] = Tag.new(dyn.read(stream), stream, method(:str_offset))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def endian
 | 
			
		||||
      header.class.self_endian
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the DT_STRTAB's +d_val+ offset related to file.
 | 
			
		||||
    def str_offset
 | 
			
		||||
      # TODO: handle DT_STRTAB not exitsts.
 | 
			
		||||
      @str_offset ||= @offset_from_vma.call(tag_by_type(:strtab).header.d_val.to_i)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # A tag class.
 | 
			
		||||
    class Tag
 | 
			
		||||
      attr_reader :header # @return [ELFTools::Structs::ELF_Dyn] The dynamic tag header.
 | 
			
		||||
      attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
 | 
			
		||||
      # Instantiate a {ELFTools::Dynamic::Tag} object.
 | 
			
		||||
      # @param [ELF_Dyn] header The dynamic tag header.
 | 
			
		||||
      # @param [#pos=, #read] stream Streaming object.
 | 
			
		||||
      # @param [Method] str_offset
 | 
			
		||||
      #   Call this method to get the string offset related
 | 
			
		||||
      #   to file.
 | 
			
		||||
      def initialize(header, stream, str_offset)
 | 
			
		||||
        @header = header
 | 
			
		||||
        @stream = stream
 | 
			
		||||
        @str_offset = str_offset
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Some dynamic have name.
 | 
			
		||||
      TYPE_WITH_NAME = [Constants::DT_NEEDED,
 | 
			
		||||
                        Constants::DT_SONAME,
 | 
			
		||||
                        Constants::DT_RPATH,
 | 
			
		||||
                        Constants::DT_RUNPATH].freeze
 | 
			
		||||
      # Return the content of this tag records.
 | 
			
		||||
      #
 | 
			
		||||
      # For normal tags, this method just return
 | 
			
		||||
      # +header.d_val+. For tags with +header.d_val+
 | 
			
		||||
      # in meaning of string offset (e.g. DT_NEEDED), this method would
 | 
			
		||||
      # return the string it specified.
 | 
			
		||||
      # Tags with type in {TYPE_WITH_NAME} are those tags with name.
 | 
			
		||||
      # @return [Integer, String] The content this tag records.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   dynamic = elf.segment_by_type(:dynamic)
 | 
			
		||||
      #   dynamic.tag_by_type(:init).value
 | 
			
		||||
      #   #=> 4195600 # 0x400510
 | 
			
		||||
      #   dynamic.tag_by_type(:needed).value
 | 
			
		||||
      #   #=> 'libc.so.6'
 | 
			
		||||
      def value
 | 
			
		||||
        name || header.d_val.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Is this tag has a name?
 | 
			
		||||
      #
 | 
			
		||||
      # The criteria here is if this tag's type is in {TYPE_WITH_NAME}.
 | 
			
		||||
      # @return [Boolean] Is this tag has a name.
 | 
			
		||||
      def name?
 | 
			
		||||
        TYPE_WITH_NAME.include?(header.d_tag)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Return the name of this tag.
 | 
			
		||||
      #
 | 
			
		||||
      # Only tags with name would return a name.
 | 
			
		||||
      # Others would return +nil+.
 | 
			
		||||
      # @return [String, nil] The name.
 | 
			
		||||
      def name
 | 
			
		||||
        return nil unless name?
 | 
			
		||||
 | 
			
		||||
        Util.cstring(stream, @str_offset.call + header.d_val.to_i)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										377
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/elf_file.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										377
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/elf_file.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,377 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/constants'
 | 
			
		||||
require 'elftools/exceptions'
 | 
			
		||||
require 'elftools/lazy_array'
 | 
			
		||||
require 'elftools/sections/sections'
 | 
			
		||||
require 'elftools/segments/segments'
 | 
			
		||||
require 'elftools/structs'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # The main class for using elftools.
 | 
			
		||||
  class ELFFile
 | 
			
		||||
    attr_reader :stream # @return [#pos=, #read] The +File+ object.
 | 
			
		||||
    attr_reader :elf_class # @return [Integer] 32 or 64.
 | 
			
		||||
    attr_reader :endian # @return [Symbol] +:little+ or +:big+.
 | 
			
		||||
 | 
			
		||||
    # Instantiate an {ELFFile} object.
 | 
			
		||||
    #
 | 
			
		||||
    # @param [#pos=, #read] stream
 | 
			
		||||
    #   The +File+ object to be fetch information from.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   ELFFile.new(File.open('/bin/cat'))
 | 
			
		||||
    #   #=> #<ELFTools::ELFFile:0x00564b106c32a0 @elf_class=64, @endian=:little, @stream=#<File:/bin/cat>>
 | 
			
		||||
    def initialize(stream)
 | 
			
		||||
      @stream = stream
 | 
			
		||||
      # always set binmode if stream is an IO object.
 | 
			
		||||
      @stream.binmode if @stream.respond_to?(:binmode)
 | 
			
		||||
      identify # fetch the most basic information
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return the file header.
 | 
			
		||||
    #
 | 
			
		||||
    # Lazy loading.
 | 
			
		||||
    # @return [ELFTools::Structs::ELF_Ehdr] The header.
 | 
			
		||||
    def header
 | 
			
		||||
      return @header if defined?(@header)
 | 
			
		||||
 | 
			
		||||
      stream.pos = 0
 | 
			
		||||
      @header = Structs::ELF_Ehdr.new(endian: endian, offset: stream.pos)
 | 
			
		||||
      @header.elf_class = elf_class
 | 
			
		||||
      @header.read(stream)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return the BuildID of ELF.
 | 
			
		||||
    # @return [String, nil]
 | 
			
		||||
    #   BuildID in hex form will be returned.
 | 
			
		||||
    #   +nil+ is returned if the .note.gnu.build-id section
 | 
			
		||||
    #   is not found.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.build_id
 | 
			
		||||
    #   #=> '73ab62cb7bc9959ce053c2b711322158708cdc07'
 | 
			
		||||
    def build_id
 | 
			
		||||
      section = section_by_name('.note.gnu.build-id')
 | 
			
		||||
      return nil if section.nil?
 | 
			
		||||
 | 
			
		||||
      note = section.notes.first
 | 
			
		||||
      return nil if note.nil?
 | 
			
		||||
 | 
			
		||||
      note.desc.unpack('H*').first
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get machine architecture.
 | 
			
		||||
    #
 | 
			
		||||
    # Mappings of architecture can be found
 | 
			
		||||
    # in {ELFTools::Constants::EM.mapping}.
 | 
			
		||||
    # @return [String]
 | 
			
		||||
    #   Name of architecture.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.machine
 | 
			
		||||
    #   #=> 'Advanced Micro Devices X86-64'
 | 
			
		||||
    def machine
 | 
			
		||||
      ELFTools::Constants::EM.mapping(header.e_machine)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return the ELF type according to +e_type+.
 | 
			
		||||
    # @return [String] Type in string format.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   ELFFile.new(File.open('spec/files/libc.so.6')).elf_type
 | 
			
		||||
    #   #=> 'DYN'
 | 
			
		||||
    #   ELFFile.new(File.open('spec/files/amd64.elf')).elf_type
 | 
			
		||||
    #   #=> 'EXEC'
 | 
			
		||||
    def elf_type
 | 
			
		||||
      ELFTools::Constants::ET.mapping(header.e_type)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #========= method about sections
 | 
			
		||||
 | 
			
		||||
    # Number of sections in this file.
 | 
			
		||||
    # @return [Integer] The desired number.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.num_sections
 | 
			
		||||
    #   #=> 29
 | 
			
		||||
    def num_sections
 | 
			
		||||
      header.e_shnum
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Acquire the section named as +name+.
 | 
			
		||||
    # @param [String] name The desired section name.
 | 
			
		||||
    # @return [ELFTools::Sections::Section, nil] The target section.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.section_by_name('.note.gnu.build-id')
 | 
			
		||||
    #   #=> #<ELFTools::Sections::Section:0x005647b1282428>
 | 
			
		||||
    #   elf.section_by_name('')
 | 
			
		||||
    #   #=> #<ELFTools::Sections::NullSection:0x005647b11da110>
 | 
			
		||||
    #   elf.section_by_name('no such section')
 | 
			
		||||
    #   #=> nil
 | 
			
		||||
    def section_by_name(name)
 | 
			
		||||
      each_sections.find { |sec| sec.name == name }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Iterate all sections.
 | 
			
		||||
    #
 | 
			
		||||
    # All sections are lazy loading, the section
 | 
			
		||||
    # only be created whenever accessing it.
 | 
			
		||||
    # This method is useful for {#section_by_name}
 | 
			
		||||
    # since not all sections need to be created.
 | 
			
		||||
    # @yieldparam [ELFTools::Sections::Section] section A section.
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    # @return [Enumerator<ELFTools::Sections::Section>, Array<ELFTools::Sections::Section>]
 | 
			
		||||
    #   As +Array#each+, if block is not given, a enumerator will be returned,
 | 
			
		||||
    #   otherwise, the whole sections will be returned.
 | 
			
		||||
    def each_sections(&block)
 | 
			
		||||
      return enum_for(:each_sections) unless block_given?
 | 
			
		||||
 | 
			
		||||
      Array.new(num_sections) do |i|
 | 
			
		||||
        section_at(i).tap(&block)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Simply use {#sections} to get all sections.
 | 
			
		||||
    # @return [Array<ELFTools::Sections::Section>]
 | 
			
		||||
    #   Whole sections.
 | 
			
		||||
    def sections
 | 
			
		||||
      each_sections.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Acquire the +n+-th section, 0-based.
 | 
			
		||||
    #
 | 
			
		||||
    # Sections are lazy loaded.
 | 
			
		||||
    # @param [Integer] n The index.
 | 
			
		||||
    # @return [ELFTools::Sections::Section, nil]
 | 
			
		||||
    #   The target section.
 | 
			
		||||
    #   If +n+ is out of bound, +nil+ is returned.
 | 
			
		||||
    def section_at(n)
 | 
			
		||||
      @sections ||= LazyArray.new(num_sections, &method(:create_section))
 | 
			
		||||
      @sections[n]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Fetch all sections with specific type.
 | 
			
		||||
    #
 | 
			
		||||
    # The available types are listed in {ELFTools::Constants::PT}.
 | 
			
		||||
    # This method accept giving block.
 | 
			
		||||
    # @param [Integer, Symbol, String] type
 | 
			
		||||
    #   The type needed, similar format as {#segment_by_type}.
 | 
			
		||||
    # @yieldparam [ELFTools::Sections::Section] section A section in specific type.
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    # @return [Array<ELFTools::Sections::section>] The target sections.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
 | 
			
		||||
    #   elf.sections_by_type(:rela)
 | 
			
		||||
    #   #=> [#<ELFTools::Sections::RelocationSection:0x00563cd3219970>,
 | 
			
		||||
    #   #    #<ELFTools::Sections::RelocationSection:0x00563cd3b89d70>]
 | 
			
		||||
    def sections_by_type(type, &block)
 | 
			
		||||
      type = Util.to_constant(Constants::SHT, type)
 | 
			
		||||
      Util.select_by_type(each_sections, type, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the string table section.
 | 
			
		||||
    #
 | 
			
		||||
    # This section is acquired by using the +e_shstrndx+
 | 
			
		||||
    # in ELF header.
 | 
			
		||||
    # @return [ELFTools::Sections::StrTabSection] The desired section.
 | 
			
		||||
    def strtab_section
 | 
			
		||||
      section_at(header.e_shstrndx)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    #========= method about segments
 | 
			
		||||
 | 
			
		||||
    # Number of segments in this file.
 | 
			
		||||
    # @return [Integer] The desited number.
 | 
			
		||||
    def num_segments
 | 
			
		||||
      header.e_phnum
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Iterate all segments.
 | 
			
		||||
    #
 | 
			
		||||
    # All segments are lazy loading, the segment
 | 
			
		||||
    # only be created whenever accessing it.
 | 
			
		||||
    # This method is useful for {#segment_by_type}
 | 
			
		||||
    # since not all segments need to be created.
 | 
			
		||||
    # @yieldparam [ELFTools::Segments::Segment] segment A segment.
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    # @return [Array<ELFTools::Segments::Segment>]
 | 
			
		||||
    #   Whole segments will be returned.
 | 
			
		||||
    def each_segments(&block)
 | 
			
		||||
      return enum_for(:each_segments) unless block_given?
 | 
			
		||||
 | 
			
		||||
      Array.new(num_segments) do |i|
 | 
			
		||||
        segment_at(i).tap(&block)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Simply use {#segments} to get all segments.
 | 
			
		||||
    # @return [Array<ELFTools::Segments::Segment>]
 | 
			
		||||
    #   Whole segments.
 | 
			
		||||
    def segments
 | 
			
		||||
      each_segments.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the first segment with +p_type=type+.
 | 
			
		||||
    # The available types are listed in {ELFTools::Constants::PT}.
 | 
			
		||||
    #
 | 
			
		||||
    # @note
 | 
			
		||||
    #   This method will return the first segment found,
 | 
			
		||||
    #   to found all segments with specific type you can use {#segments_by_type}.
 | 
			
		||||
    # @param [Integer, Symbol, String] type
 | 
			
		||||
    #   See examples for clear usage.
 | 
			
		||||
    # @return [ELFTools::Segments::Segment] The target segment.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   # type as an integer
 | 
			
		||||
    #   elf.segment_by_type(ELFTools::Constants::PT_NOTE)
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    #
 | 
			
		||||
    #   elf.segment_by_type(4) # PT_NOTE
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    #
 | 
			
		||||
    #   # type as a symbol
 | 
			
		||||
    #   elf.segment_by_type(:PT_NOTE)
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    #
 | 
			
		||||
    #   # you can do this
 | 
			
		||||
    #   elf.segment_by_type(:note) # will be transformed into `PT_NOTE`
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    #
 | 
			
		||||
    #   # type as a string
 | 
			
		||||
    #   elf.segment_by_type('PT_NOTE')
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    #
 | 
			
		||||
    #   # this is ok
 | 
			
		||||
    #   elf.segment_by_type('note') # will be tranformed into `PT_NOTE`
 | 
			
		||||
    #   #=>  #<ELFTools::Segments::NoteSegment:0x005629dda1e4f8>
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.segment_by_type(1337)
 | 
			
		||||
    #   # ArgumentError: No constants in Constants::PT is 1337
 | 
			
		||||
    #
 | 
			
		||||
    #   elf.segment_by_type('oao')
 | 
			
		||||
    #   # ArgumentError: No constants in Constants::PT named "PT_OAO"
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf.segment_by_type(0)
 | 
			
		||||
    #   #=> nil # no such segment exists
 | 
			
		||||
    def segment_by_type(type)
 | 
			
		||||
      type = Util.to_constant(Constants::PT, type)
 | 
			
		||||
      each_segments.find { |seg| seg.header.p_type == type }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Fetch all segments with specific type.
 | 
			
		||||
    #
 | 
			
		||||
    # If you want to find only one segment,
 | 
			
		||||
    # use {#segment_by_type} instead.
 | 
			
		||||
    # This method accept giving block.
 | 
			
		||||
    # @param [Integer, Symbol, String] type
 | 
			
		||||
    #   The type needed, same format as {#segment_by_type}.
 | 
			
		||||
    # @yieldparam [ELFTools::Segments::Segment] segment A segment in specific type.
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    # @return [Array<ELFTools::Segments::Segment>] The target segments.
 | 
			
		||||
    def segments_by_type(type, &block)
 | 
			
		||||
      type = Util.to_constant(Constants::PT, type)
 | 
			
		||||
      Util.select_by_type(each_segments, type, &block)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Acquire the +n+-th segment, 0-based.
 | 
			
		||||
    #
 | 
			
		||||
    # Segments are lazy loaded.
 | 
			
		||||
    # @param [Integer] n The index.
 | 
			
		||||
    # @return [ELFTools::Segments::Segment, nil]
 | 
			
		||||
    #   The target segment.
 | 
			
		||||
    #   If +n+ is out of bound, +nil+ is returned.
 | 
			
		||||
    def segment_at(n)
 | 
			
		||||
      @segments ||= LazyArray.new(num_segments, &method(:create_segment))
 | 
			
		||||
      @segments[n]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the offset related to file, given virtual memory address.
 | 
			
		||||
    #
 | 
			
		||||
    # This method should work no matter ELF is a PIE or not.
 | 
			
		||||
    # This method refers from (actually equals to) binutils/readelf.c#offset_from_vma.
 | 
			
		||||
    # @param [Integer] vma The virtual address to be queried.
 | 
			
		||||
    # @return [Integer] Related file offset.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   elf = ELFTools::ELFFile.new(File.open('/bin/cat'))
 | 
			
		||||
    #   elf.offset_from_vma(0x401337)
 | 
			
		||||
    #   #=> 4919 # 0x1337
 | 
			
		||||
    def offset_from_vma(vma, size = 0)
 | 
			
		||||
      segments_by_type(:load) do |seg|
 | 
			
		||||
        return seg.vma_to_offset(vma) if seg.vma_in?(vma, size)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # The patch status.
 | 
			
		||||
    # @return [Hash{Integer => String}]
 | 
			
		||||
    def patches
 | 
			
		||||
      patch = {}
 | 
			
		||||
      loaded_headers.each do |header|
 | 
			
		||||
        header.patches.each do |key, val|
 | 
			
		||||
          patch[key + header.offset] = val
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      patch
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Apply patches and save as +filename+.
 | 
			
		||||
    #
 | 
			
		||||
    # @param [String] filename
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def save(filename)
 | 
			
		||||
      stream.pos = 0
 | 
			
		||||
      all = stream.read.force_encoding('ascii-8bit')
 | 
			
		||||
      patches.each do |pos, val|
 | 
			
		||||
        all[pos, val.size] = val
 | 
			
		||||
      end
 | 
			
		||||
      IO.binwrite(filename, all)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    # bad idea..
 | 
			
		||||
    def loaded_headers
 | 
			
		||||
      explore = lambda do |obj|
 | 
			
		||||
        return obj if obj.is_a?(::ELFTools::Structs::ELFStruct)
 | 
			
		||||
        return obj.map(&explore) if obj.is_a?(Array)
 | 
			
		||||
 | 
			
		||||
        obj.instance_variables.map do |s|
 | 
			
		||||
          explore.call(obj.instance_variable_get(s))
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      explore.call(self).flatten
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def identify
 | 
			
		||||
      stream.pos = 0
 | 
			
		||||
      magic = stream.read(4)
 | 
			
		||||
      raise ELFMagicError, "Invalid magic number #{magic.inspect}" unless magic == Constants::ELFMAG
 | 
			
		||||
 | 
			
		||||
      ei_class = stream.read(1).ord
 | 
			
		||||
      @elf_class = {
 | 
			
		||||
        1 => 32,
 | 
			
		||||
        2 => 64
 | 
			
		||||
      }[ei_class]
 | 
			
		||||
      raise ELFClassError, format('Invalid EI_CLASS "\x%02x"', ei_class) if elf_class.nil?
 | 
			
		||||
 | 
			
		||||
      ei_data = stream.read(1).ord
 | 
			
		||||
      @endian = {
 | 
			
		||||
        1 => :little,
 | 
			
		||||
        2 => :big
 | 
			
		||||
      }[ei_data]
 | 
			
		||||
      raise ELFDataError, format('Invalid EI_DATA "\x%02x"', ei_data) if endian.nil?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_section(n)
 | 
			
		||||
      stream.pos = header.e_shoff + n * header.e_shentsize
 | 
			
		||||
      shdr = Structs::ELF_Shdr.new(endian: endian, offset: stream.pos)
 | 
			
		||||
      shdr.elf_class = elf_class
 | 
			
		||||
      shdr.read(stream)
 | 
			
		||||
      Sections::Section.create(shdr, stream,
 | 
			
		||||
                               offset_from_vma: method(:offset_from_vma),
 | 
			
		||||
                               strtab: method(:strtab_section),
 | 
			
		||||
                               section_at: method(:section_at))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_segment(n)
 | 
			
		||||
      stream.pos = header.e_phoff + n * header.e_phentsize
 | 
			
		||||
      phdr = Structs::ELF_Phdr[elf_class].new(endian: endian, offset: stream.pos)
 | 
			
		||||
      phdr.elf_class = elf_class
 | 
			
		||||
      Segments::Segment.create(phdr.read(stream), stream, offset_from_vma: method(:offset_from_vma))
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										15
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/exceptions.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/exceptions.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Being raised when parsing error.
 | 
			
		||||
  class ELFError < StandardError; end
 | 
			
		||||
 | 
			
		||||
  # Raised on invalid ELF magic.
 | 
			
		||||
  class ELFMagicError < ELFError; end
 | 
			
		||||
 | 
			
		||||
  # Raised on invalid ELF class (EI_CLASS).
 | 
			
		||||
  class ELFClassError < ELFError; end
 | 
			
		||||
 | 
			
		||||
  # Raised on invalid ELF data encoding (EI_DATA).
 | 
			
		||||
  class ELFDataError < ELFError; end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										47
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/lazy_array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/lazy_array.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # A helper class for {ELFTools} easy to implement
 | 
			
		||||
  # 'lazy loading' objects.
 | 
			
		||||
  # Mainly used when loading sections, segments, and
 | 
			
		||||
  # symbols.
 | 
			
		||||
  class LazyArray
 | 
			
		||||
    # Instantiate a {LazyArray} object.
 | 
			
		||||
    # @param [Integer] size
 | 
			
		||||
    #   The size of array.
 | 
			
		||||
    # @yieldparam [Integer] i
 | 
			
		||||
    #   Needs the +i+-th element.
 | 
			
		||||
    # @yieldreturn [Object]
 | 
			
		||||
    #   Value of the +i+-th element.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   arr = LazyArray.new(10) { |i| p "calc #{i}"; i * i }
 | 
			
		||||
    #   p arr[2]
 | 
			
		||||
    #   # "calc 2"
 | 
			
		||||
    #   # 4
 | 
			
		||||
    #
 | 
			
		||||
    #   p arr[3]
 | 
			
		||||
    #   # "calc 3"
 | 
			
		||||
    #   # 9
 | 
			
		||||
    #
 | 
			
		||||
    #   p arr[3]
 | 
			
		||||
    #   # 9
 | 
			
		||||
    def initialize(size, &block)
 | 
			
		||||
      @internal = Array.new(size)
 | 
			
		||||
      @block = block
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # To access elements like a normal array.
 | 
			
		||||
    #
 | 
			
		||||
    # Elements are lazy loaded at the first time
 | 
			
		||||
    # access it.
 | 
			
		||||
    # @return [Object]
 | 
			
		||||
    #   The element, returned type is the
 | 
			
		||||
    #   return type of block given in {#initialize}.
 | 
			
		||||
    def [](i)
 | 
			
		||||
      # XXX: support negative index?
 | 
			
		||||
      return nil unless i.between?(0, @internal.size - 1)
 | 
			
		||||
 | 
			
		||||
      @internal[i] ||= @block.call(i)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										125
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/note.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/note.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/structs'
 | 
			
		||||
require 'elftools/util'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Since both note sections and note segments refer to notes, this module
 | 
			
		||||
  # defines common methods for {ELFTools::Sections::NoteSection} and
 | 
			
		||||
  # {ELFTools::Segments::NoteSegment}.
 | 
			
		||||
  #
 | 
			
		||||
  # @note
 | 
			
		||||
  #   This module can only be included in {ELFTools::Sections::NoteSection} and
 | 
			
		||||
  #   {ELFTools::Segments::NoteSegment} since some methods here assume some
 | 
			
		||||
  #   attributes already exist.
 | 
			
		||||
  module Note
 | 
			
		||||
    # Since size of {ELFTools::Structs::ELF_Nhdr} will not change no matter in
 | 
			
		||||
    # what endian and what arch, we can do this here. This value should equal
 | 
			
		||||
    # to 12.
 | 
			
		||||
    SIZE_OF_NHDR = Structs::ELF_Nhdr.new(endian: :little).num_bytes
 | 
			
		||||
 | 
			
		||||
    # Iterate all notes in a note section or segment.
 | 
			
		||||
    #
 | 
			
		||||
    # Structure of notes are:
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #   | Note 1 header |
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #   |  Note 1 name  |
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #   |  Note 1 desc  |
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #   | Note 2 header |
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #   |      ...      |
 | 
			
		||||
    #   +---------------+
 | 
			
		||||
    #
 | 
			
		||||
    # @note
 | 
			
		||||
    #   This method assume following methods exist:
 | 
			
		||||
    #     stream
 | 
			
		||||
    #     note_start
 | 
			
		||||
    #     note_total_size
 | 
			
		||||
    # @return [Enumerator<ELFTools::Note::Note>, Array<ELFTools::Note::Note>]
 | 
			
		||||
    #   If block is not given, an enumerator will be returned.
 | 
			
		||||
    #   Otherwise, return the array of notes.
 | 
			
		||||
    def each_notes
 | 
			
		||||
      return enum_for(:each_notes) unless block_given?
 | 
			
		||||
 | 
			
		||||
      @notes_offset_map ||= {}
 | 
			
		||||
      cur = note_start
 | 
			
		||||
      notes = []
 | 
			
		||||
      while cur < note_start + note_total_size
 | 
			
		||||
        stream.pos = cur
 | 
			
		||||
        @notes_offset_map[cur] ||= create_note(cur)
 | 
			
		||||
        note = @notes_offset_map[cur]
 | 
			
		||||
        # name and desc size needs to be 4-bytes align
 | 
			
		||||
        name_size = Util.align(note.header.n_namesz, 2)
 | 
			
		||||
        desc_size = Util.align(note.header.n_descsz, 2)
 | 
			
		||||
        cur += SIZE_OF_NHDR + name_size + desc_size
 | 
			
		||||
        notes << note
 | 
			
		||||
        yield note
 | 
			
		||||
      end
 | 
			
		||||
      notes
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Simply +#notes+ to get all notes.
 | 
			
		||||
    # @return [Array<ELFTools::Note::Note>]
 | 
			
		||||
    #   Whole notes.
 | 
			
		||||
    def notes
 | 
			
		||||
      each_notes.to_a
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    # Get the endian.
 | 
			
		||||
    #
 | 
			
		||||
    # @note This method assume method +header+ exists.
 | 
			
		||||
    # @return [Symbol] +:little+ or +:big+.
 | 
			
		||||
    def endian
 | 
			
		||||
      header.class.self_endian
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def create_note(cur)
 | 
			
		||||
      nhdr = Structs::ELF_Nhdr.new(endian: endian, offset: stream.pos).read(stream)
 | 
			
		||||
      ELFTools::Note::Note.new(nhdr, stream, cur)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Class of a note.
 | 
			
		||||
    class Note
 | 
			
		||||
      attr_reader :header # @return [ELFTools::Structs::ELF_Nhdr] Note header.
 | 
			
		||||
      attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
      attr_reader :offset # @return [Integer] Address of this note start, includes note header.
 | 
			
		||||
 | 
			
		||||
      # Instantiate a {ELFTools::Note::Note} object.
 | 
			
		||||
      # @param [ELF_Nhdr] header The note header.
 | 
			
		||||
      # @param [#pos=, #read] stream Streaming object.
 | 
			
		||||
      # @param [Integer] offset
 | 
			
		||||
      #   Start address of this note, includes the header.
 | 
			
		||||
      def initialize(header, stream, offset)
 | 
			
		||||
        @header = header
 | 
			
		||||
        @stream = stream
 | 
			
		||||
        @offset = offset
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Name of this note.
 | 
			
		||||
      # @return [String] The name.
 | 
			
		||||
      def name
 | 
			
		||||
        return @name if defined?(@name)
 | 
			
		||||
 | 
			
		||||
        stream.pos = @offset + SIZE_OF_NHDR
 | 
			
		||||
        @name = stream.read(header.n_namesz)[0..-2]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Description of this note.
 | 
			
		||||
      # @return [String] The description.
 | 
			
		||||
      def desc
 | 
			
		||||
        return @desc if instance_variable_defined?(:@desc)
 | 
			
		||||
 | 
			
		||||
        stream.pos = @offset + SIZE_OF_NHDR + Util.align(header.n_namesz, 2)
 | 
			
		||||
        @desc = stream.read(header.n_descsz)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # If someone likes to use full name.
 | 
			
		||||
      alias description desc
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/dynamic'
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class for dynamic table section.
 | 
			
		||||
    #
 | 
			
		||||
    # This section should always be named .dynamic.
 | 
			
		||||
    # This class knows how to get the list of dynamic tags.
 | 
			
		||||
    class DynamicSection < Section
 | 
			
		||||
      include ELFTools::Dynamic
 | 
			
		||||
 | 
			
		||||
      # Get the start address of tags.
 | 
			
		||||
      # @return [Integer] Start address of tags.
 | 
			
		||||
      def tag_start
 | 
			
		||||
        header.sh_offset
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,27 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/note'
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class of note section.
 | 
			
		||||
    # Note section records notes
 | 
			
		||||
    class NoteSection < Section
 | 
			
		||||
      # Load note related methods.
 | 
			
		||||
      include ELFTools::Note
 | 
			
		||||
 | 
			
		||||
      # Address offset of notes start.
 | 
			
		||||
      # @return [Integer] The offset.
 | 
			
		||||
      def note_start
 | 
			
		||||
        header.sh_offset
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # The total size of notes in this section.
 | 
			
		||||
      # @return [Integer] The size.
 | 
			
		||||
      def note_total_size
 | 
			
		||||
        header.sh_size
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class of null section.
 | 
			
		||||
    # Null section is for specific the end
 | 
			
		||||
    # of linked list (+sh_link+) between sections.
 | 
			
		||||
    class NullSection < Section
 | 
			
		||||
      # Is this a null section?
 | 
			
		||||
      # @return [Boolean] Yes it is.
 | 
			
		||||
      def null?
 | 
			
		||||
        true
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,109 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/constants'
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
require 'elftools/structs'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class of note section.
 | 
			
		||||
    # Note section records notes
 | 
			
		||||
    class RelocationSection < Section
 | 
			
		||||
      # Is this relocation a RELA or REL type.
 | 
			
		||||
      # @return [Boolean] If is RELA.
 | 
			
		||||
      def rela?
 | 
			
		||||
        header.sh_type == Constants::SHT_RELA
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Number of relocations in this section.
 | 
			
		||||
      # @return [Integer] The number.
 | 
			
		||||
      def num_relocations
 | 
			
		||||
        header.sh_size / header.sh_entsize
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Acquire the +n+-th relocation, 0-based.
 | 
			
		||||
      #
 | 
			
		||||
      # relocations are lazy loaded.
 | 
			
		||||
      # @param [Integer] n The index.
 | 
			
		||||
      # @return [ELFTools::Relocation, nil]
 | 
			
		||||
      #   The target relocation.
 | 
			
		||||
      #   If +n+ is out of bound, +nil+ is returned.
 | 
			
		||||
      def relocation_at(n)
 | 
			
		||||
        @relocations ||= LazyArray.new(num_relocations, &method(:create_relocation))
 | 
			
		||||
        @relocations[n]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Iterate all relocations.
 | 
			
		||||
      #
 | 
			
		||||
      # All relocations are lazy loading, the relocation
 | 
			
		||||
      # only be created whenever accessing it.
 | 
			
		||||
      # @yieldparam [ELFTools::Relocation] rel A relocation object.
 | 
			
		||||
      # @yieldreturn [void]
 | 
			
		||||
      # @return [Enumerator<ELFTools::Relocation>, Array<ELFTools::Relocation>]
 | 
			
		||||
      #   If block is not given, an enumerator will be returned.
 | 
			
		||||
      #   Otherwise, the whole relocations will be returned.
 | 
			
		||||
      def each_relocations(&block)
 | 
			
		||||
        return enum_for(:each_relocations) unless block_given?
 | 
			
		||||
 | 
			
		||||
        Array.new(num_relocations) do |i|
 | 
			
		||||
          relocation_at(i).tap(&block)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Simply use {#relocations} to get all relocations.
 | 
			
		||||
      # @return [Array<ELFTools::Relocation>]
 | 
			
		||||
      #   Whole relocations.
 | 
			
		||||
      def relocations
 | 
			
		||||
        each_relocations.to_a
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def create_relocation(n)
 | 
			
		||||
        stream.pos = header.sh_offset + n * header.sh_entsize
 | 
			
		||||
        klass = rela? ? Structs::ELF_Rela : Structs::ELF_Rel
 | 
			
		||||
        rel = klass.new(endian: header.class.self_endian, offset: stream.pos)
 | 
			
		||||
        rel.elf_class = header.elf_class
 | 
			
		||||
        rel.read(stream)
 | 
			
		||||
        Relocation.new(rel, stream)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # A relocation entry.
 | 
			
		||||
  #
 | 
			
		||||
  # Can be either a REL or RELA relocation.
 | 
			
		||||
  # XXX: move this to an independent file?
 | 
			
		||||
  class Relocation
 | 
			
		||||
    attr_reader :header # @return [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] Rel(a) header.
 | 
			
		||||
    attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
 | 
			
		||||
    # Instantiate a {Relocation} object.
 | 
			
		||||
    def initialize(header, stream)
 | 
			
		||||
      @header = header
 | 
			
		||||
      @stream = stream
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # +r_info+ contains sym and type, use two methods
 | 
			
		||||
    # to access them easier.
 | 
			
		||||
    # @return [Integer] sym infor.
 | 
			
		||||
    def r_info_sym
 | 
			
		||||
      header.r_info >> mask_bit
 | 
			
		||||
    end
 | 
			
		||||
    alias symbol_index r_info_sym
 | 
			
		||||
 | 
			
		||||
    # +r_info+ contains sym and type, use two methods
 | 
			
		||||
    # to access them easier.
 | 
			
		||||
    # @return [Integer] type infor.
 | 
			
		||||
    def r_info_type
 | 
			
		||||
      header.r_info & ((1 << mask_bit) - 1)
 | 
			
		||||
    end
 | 
			
		||||
    alias type r_info_type
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def mask_bit
 | 
			
		||||
      header.elf_class == 32 ? 8 : 32
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										56
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/sections/section.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/sections/section.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/constants'
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Base class of sections.
 | 
			
		||||
    class Section
 | 
			
		||||
      attr_reader :header # @return [ELFTools::Structs::ELF_Shdr] Section header.
 | 
			
		||||
      attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
 | 
			
		||||
      # Instantiate a {Section} object.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF_Shdr] header
 | 
			
		||||
      #   The section header object.
 | 
			
		||||
      # @param [#pos=, #read] stream
 | 
			
		||||
      #   The streaming object for further dump.
 | 
			
		||||
      # @param [ELFTools::Sections::StrTabSection, Proc] strtab
 | 
			
		||||
      #   The string table object. For fetching section names.
 | 
			
		||||
      #   If +Proc+ if given, it will call at the first
 | 
			
		||||
      #   time access +#name+.
 | 
			
		||||
      # @param [Method] offset_from_vma
 | 
			
		||||
      #   The method to get offset of file, given virtual memory address.
 | 
			
		||||
      def initialize(header, stream, offset_from_vma: nil, strtab: nil, **_kwargs)
 | 
			
		||||
        @header = header
 | 
			
		||||
        @stream = stream
 | 
			
		||||
        @strtab = strtab
 | 
			
		||||
        @offset_from_vma = offset_from_vma
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Return +header.sh_type+ in a simplier way.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The type, meaning of types are defined in {Constants::SHT}.
 | 
			
		||||
      def type
 | 
			
		||||
        header.sh_type.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Get name of this section.
 | 
			
		||||
      # @return [String] The name.
 | 
			
		||||
      def name
 | 
			
		||||
        @name ||= @strtab.call.name_at(header.sh_name)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Fetch data of this section.
 | 
			
		||||
      # @return [String] Data.
 | 
			
		||||
      def data
 | 
			
		||||
        stream.pos = header.sh_offset
 | 
			
		||||
        stream.read(header.sh_size)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Is this a null section?
 | 
			
		||||
      # @return [Boolean] No it's not.
 | 
			
		||||
      def null?
 | 
			
		||||
        false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										38
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/sections/sections.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/sections/sections.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
# Require this file to load all sections classes.
 | 
			
		||||
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
 | 
			
		||||
require 'elftools/sections/dynamic_section'
 | 
			
		||||
require 'elftools/sections/note_section'
 | 
			
		||||
require 'elftools/sections/null_section'
 | 
			
		||||
require 'elftools/sections/relocation_section'
 | 
			
		||||
require 'elftools/sections/str_tab_section'
 | 
			
		||||
require 'elftools/sections/sym_tab_section'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Defines different types of sections in this module.
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class methods of {Sections::Section}.
 | 
			
		||||
    class << Section
 | 
			
		||||
      # Use different class according to +header.sh_type+.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF_Shdr] header Section header.
 | 
			
		||||
      # @param [#pos=, #read] stream Streaming object.
 | 
			
		||||
      # @return [ELFTools::Sections::Section]
 | 
			
		||||
      #   Return object dependes on +header.sh_type+.
 | 
			
		||||
      def create(header, stream, *args, **kwargs)
 | 
			
		||||
        klass = case header.sh_type
 | 
			
		||||
                when Constants::SHT_DYNAMIC then DynamicSection
 | 
			
		||||
                when Constants::SHT_NULL then NullSection
 | 
			
		||||
                when Constants::SHT_NOTE then NoteSection
 | 
			
		||||
                when Constants::SHT_RELA, Constants::SHT_REL then RelocationSection
 | 
			
		||||
                when Constants::SHT_STRTAB then StrTabSection
 | 
			
		||||
                when Constants::SHT_SYMTAB, Constants::SHT_DYNSYM then SymTabSection
 | 
			
		||||
                else Section
 | 
			
		||||
                end
 | 
			
		||||
        klass.new(header, stream, *args, **kwargs)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
require 'elftools/util'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class of string table section.
 | 
			
		||||
    # Usually for section .strtab and .dynstr,
 | 
			
		||||
    # which record names.
 | 
			
		||||
    class StrTabSection < Section
 | 
			
		||||
      # Return the section or symbol name.
 | 
			
		||||
      # @param [Integer] offset
 | 
			
		||||
      #   Usually from +shdr.sh_name+ or +sym.st_name+.
 | 
			
		||||
      # @return [String] The name without null bytes.
 | 
			
		||||
      def name_at(offset)
 | 
			
		||||
        Util.cstring(stream, header.sh_offset + offset)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,127 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/sections/section'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Sections
 | 
			
		||||
    # Class of symbol table section.
 | 
			
		||||
    # Usually for section .symtab and .dynsym,
 | 
			
		||||
    # which will refer to symbols in ELF file.
 | 
			
		||||
    class SymTabSection < Section
 | 
			
		||||
      # Instantiate a {SymTabSection} object.
 | 
			
		||||
      # There's a +section_at+ lambda for {SymTabSection}
 | 
			
		||||
      # to easily fetch other sections.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF_Shdr] header
 | 
			
		||||
      #   See {Section#initialize} for more information.
 | 
			
		||||
      # @param [#pos=, #read] stream
 | 
			
		||||
      #   See {Section#initialize} for more information.
 | 
			
		||||
      # @param [Proc] section_at
 | 
			
		||||
      #   The method for fetching other sections by index.
 | 
			
		||||
      #   This lambda should be {ELFTools::ELFFile#section_at}.
 | 
			
		||||
      def initialize(header, stream, section_at: nil, **_kwargs)
 | 
			
		||||
        @section_at = section_at
 | 
			
		||||
        # For faster #symbol_by_name
 | 
			
		||||
        super
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Number of symbols.
 | 
			
		||||
      # @return [Integer] The number.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   symtab.num_symbols
 | 
			
		||||
      #   #=> 75
 | 
			
		||||
      def num_symbols
 | 
			
		||||
        header.sh_size / header.sh_entsize
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Acquire the +n+-th symbol, 0-based.
 | 
			
		||||
      #
 | 
			
		||||
      # Symbols are lazy loaded.
 | 
			
		||||
      # @param [Integer] n The index.
 | 
			
		||||
      # @return [ELFTools::Sections::Symbol, nil]
 | 
			
		||||
      #   The target symbol.
 | 
			
		||||
      #   If +n+ is out of bound, +nil+ is returned.
 | 
			
		||||
      def symbol_at(n)
 | 
			
		||||
        @symbols ||= LazyArray.new(num_symbols, &method(:create_symbol))
 | 
			
		||||
        @symbols[n]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Iterate all symbols.
 | 
			
		||||
      #
 | 
			
		||||
      # All symbols are lazy loading, the symbol
 | 
			
		||||
      # only be created whenever accessing it.
 | 
			
		||||
      # This method is useful for {#symbol_by_name}
 | 
			
		||||
      # since not all symbols need to be created.
 | 
			
		||||
      # @yieldparam [ELFTools::Sections::Symbol] sym A symbol object.
 | 
			
		||||
      # @yieldreturn [void]
 | 
			
		||||
      # @return [Enumerator<ELFTools::Sections::Symbol>, Array<ELFTools::Sections::Symbol>]
 | 
			
		||||
      #   If block is not given, an enumerator will be returned.
 | 
			
		||||
      #   Otherwise return array of symbols.
 | 
			
		||||
      def each_symbols(&block)
 | 
			
		||||
        return enum_for(:each_symbols) unless block_given?
 | 
			
		||||
 | 
			
		||||
        Array.new(num_symbols) do |i|
 | 
			
		||||
          symbol_at(i).tap(&block)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Simply use {#symbols} to get all symbols.
 | 
			
		||||
      # @return [Array<ELFTools::Sections::Symbol>]
 | 
			
		||||
      #   The whole symbols.
 | 
			
		||||
      def symbols
 | 
			
		||||
        each_symbols.to_a
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Get symbol by its name.
 | 
			
		||||
      # @param [String] name
 | 
			
		||||
      #   The name of symbol.
 | 
			
		||||
      # @return [ELFTools::Sections::Symbol] Desired symbol.
 | 
			
		||||
      def symbol_by_name(name)
 | 
			
		||||
        each_symbols.find { |symbol| symbol.name == name }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Return the symbol string section.
 | 
			
		||||
      # Lazy loaded.
 | 
			
		||||
      # @return [ELFTools::Sections::StrTabSection] The string table section.
 | 
			
		||||
      def symstr
 | 
			
		||||
        @symstr ||= @section_at.call(header.sh_link)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      def create_symbol(n)
 | 
			
		||||
        stream.pos = header.sh_offset + n * header.sh_entsize
 | 
			
		||||
        sym = Structs::ELF_sym[header.elf_class].new(endian: header.class.self_endian, offset: stream.pos)
 | 
			
		||||
        sym.read(stream)
 | 
			
		||||
        Symbol.new(sym, stream, symstr: method(:symstr))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Class of symbol.
 | 
			
		||||
    #
 | 
			
		||||
    # XXX: Should this class be defined in an independent file?
 | 
			
		||||
    class Symbol
 | 
			
		||||
      attr_reader :header # @return [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] Section header.
 | 
			
		||||
      attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
 | 
			
		||||
      # Instantiate a {ELFTools::Sections::Symbol} object.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] header
 | 
			
		||||
      #   The symbol header.
 | 
			
		||||
      # @param [#pos=, #read] stream The streaming object.
 | 
			
		||||
      # @param [ELFTools::Sections::StrTabSection, Proc] symstr
 | 
			
		||||
      #   The symbol string section.
 | 
			
		||||
      #   If +Proc+ is given, it will be called at the first time
 | 
			
		||||
      #   access {Symbol#name}.
 | 
			
		||||
      def initialize(header, stream, symstr: nil)
 | 
			
		||||
        @header = header
 | 
			
		||||
        @stream = stream
 | 
			
		||||
        @symstr = symstr
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Return the symbol name.
 | 
			
		||||
      # @return [String] The name.
 | 
			
		||||
      def name
 | 
			
		||||
        @name ||= @symstr.call.name_at(header.st_name)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/segments/segment'
 | 
			
		||||
require 'elftools/dynamic'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Segments
 | 
			
		||||
    # Class for dynamic table segment.
 | 
			
		||||
    #
 | 
			
		||||
    # This class knows how to get the list of dynamic tags.
 | 
			
		||||
    class DynamicSegment < Segment
 | 
			
		||||
      include Dynamic # rock!
 | 
			
		||||
      # Get the start address of tags.
 | 
			
		||||
      # @return [Integer] Start address of tags.
 | 
			
		||||
      def tag_start
 | 
			
		||||
        header.p_offset
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/segments/segment'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Segments
 | 
			
		||||
    # For DT_INTERP segment, knows how to get path of
 | 
			
		||||
    # ELF interpreter.
 | 
			
		||||
    class InterpSegment < Segment
 | 
			
		||||
      # Get the path of interpreter.
 | 
			
		||||
      # @return [String] Path to the interpreter.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   interp_segment.interp_name
 | 
			
		||||
      #   #=> '/lib64/ld-linux-x86-64.so.2'
 | 
			
		||||
      def interp_name
 | 
			
		||||
        data[0..-2] # remove last null byte
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,91 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/segments/segment'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Segments
 | 
			
		||||
    # For DT_LOAD segment.
 | 
			
		||||
    # Able to query between file offset and virtual memory address.
 | 
			
		||||
    class LoadSegment < Segment
 | 
			
		||||
      # Returns the start of this segment.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The file offset.
 | 
			
		||||
      def file_head
 | 
			
		||||
        header.p_offset.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns size in file.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The size.
 | 
			
		||||
      def size
 | 
			
		||||
        header.p_filesz.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the end of this segment.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The file offset.
 | 
			
		||||
      def file_tail
 | 
			
		||||
        file_head + size
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the start virtual address of this segment.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The vma.
 | 
			
		||||
      def mem_head
 | 
			
		||||
        header.p_vaddr.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns size in memory.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The size.
 | 
			
		||||
      def mem_size
 | 
			
		||||
        header.p_memsz.to_i
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns the end virtual address of this segment.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The vma.
 | 
			
		||||
      def mem_tail
 | 
			
		||||
        mem_head + mem_size
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Query if the given file offset located in this segment.
 | 
			
		||||
      # @param [Integer] offset
 | 
			
		||||
      #   File offset.
 | 
			
		||||
      # @param [Integer] size
 | 
			
		||||
      #   Size.
 | 
			
		||||
      # @return [Boolean]
 | 
			
		||||
      def offset_in?(offset, size = 0)
 | 
			
		||||
        file_head <= offset && offset + size < file_tail
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Convert file offset into virtual memory address.
 | 
			
		||||
      # @param [Integer] offset
 | 
			
		||||
      #   File offset.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      def offset_to_vma(offset)
 | 
			
		||||
        # XXX: What if file_head is not aligned with p_vaddr (which is invalid according to ELF spec)?
 | 
			
		||||
        offset - file_head + header.p_vaddr
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Query if the given virtual memory address located in this segment.
 | 
			
		||||
      # @param [Integer] vma
 | 
			
		||||
      #   Virtual memory address.
 | 
			
		||||
      # @param [Integer] size
 | 
			
		||||
      #   Size.
 | 
			
		||||
      # @return [Boolean]
 | 
			
		||||
      def vma_in?(vma, size = 0)
 | 
			
		||||
        vma >= (header.p_vaddr & -header.p_align) &&
 | 
			
		||||
          vma + size <= mem_tail
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Convert virtual memory address into file offset.
 | 
			
		||||
      # @param [Integer] vma
 | 
			
		||||
      #   Virtual memory address.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      def vma_to_offset(vma)
 | 
			
		||||
        vma - header.p_vaddr + header.p_offset
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/note'
 | 
			
		||||
require 'elftools/segments/segment'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Segments
 | 
			
		||||
    # Class of note segment.
 | 
			
		||||
    class NoteSegment < Segment
 | 
			
		||||
      # Load note related methods.
 | 
			
		||||
      include ELFTools::Note
 | 
			
		||||
 | 
			
		||||
      # Address offset of notes start.
 | 
			
		||||
      # @return [Integer] The offset.
 | 
			
		||||
      def note_start
 | 
			
		||||
        header.p_offset
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # The total size of notes in this segment.
 | 
			
		||||
      # @return [Integer] The size.
 | 
			
		||||
      def note_total_size
 | 
			
		||||
        header.p_filesz
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										56
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/segments/segment.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/segments/segment.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  module Segments
 | 
			
		||||
    # Base class of segments.
 | 
			
		||||
    class Segment
 | 
			
		||||
      attr_reader :header # @return [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] Program header.
 | 
			
		||||
      attr_reader :stream # @return [#pos=, #read] Streaming object.
 | 
			
		||||
 | 
			
		||||
      # Instantiate a {Segment} object.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header
 | 
			
		||||
      #   Program header.
 | 
			
		||||
      # @param [#pos=, #read] stream
 | 
			
		||||
      #   Streaming object.
 | 
			
		||||
      # @param [Method] offset_from_vma
 | 
			
		||||
      #   The method to get offset of file, given virtual memory address.
 | 
			
		||||
      def initialize(header, stream, offset_from_vma: nil)
 | 
			
		||||
        @header = header
 | 
			
		||||
        @stream = stream
 | 
			
		||||
        @offset_from_vma = offset_from_vma
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Return +header.p_type+ in a simplier way.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   The type, meaning of types are defined in {Constants::PT}.
 | 
			
		||||
      def type
 | 
			
		||||
        header.p_type
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # The content in this segment.
 | 
			
		||||
      # @return [String] The content.
 | 
			
		||||
      def data
 | 
			
		||||
        stream.pos = header.p_offset
 | 
			
		||||
        stream.read(header.p_filesz)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Is this segment readable?
 | 
			
		||||
      # @return [Boolean] Ture or false.
 | 
			
		||||
      def readable?
 | 
			
		||||
        (header.p_flags & 4) == 4
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Is this segment writable?
 | 
			
		||||
      # @return [Boolean] Ture or false.
 | 
			
		||||
      def writable?
 | 
			
		||||
        (header.p_flags & 2) == 2
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Is this segment executable?
 | 
			
		||||
      # @return [Boolean] Ture or false.
 | 
			
		||||
      def executable?
 | 
			
		||||
        (header.p_flags & 1) == 1
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										34
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/segments/segments.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/segments/segments.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
# Require this file to load all segment classes.
 | 
			
		||||
 | 
			
		||||
require 'elftools/segments/segment'
 | 
			
		||||
 | 
			
		||||
require 'elftools/segments/dynamic_segment'
 | 
			
		||||
require 'elftools/segments/interp_segment'
 | 
			
		||||
require 'elftools/segments/load_segment'
 | 
			
		||||
require 'elftools/segments/note_segment'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Module for defining different types of segments.
 | 
			
		||||
  module Segments
 | 
			
		||||
    # Class methods of {Segments::Segment}.
 | 
			
		||||
    class << Segment
 | 
			
		||||
      # Use different class according to +header.p_type+.
 | 
			
		||||
      # @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header Program header of a segment.
 | 
			
		||||
      # @param [#pos=, #read] stream Streaming object.
 | 
			
		||||
      # @return [ELFTools::Segments::Segment]
 | 
			
		||||
      #   Return object dependes on +header.p_type+.
 | 
			
		||||
      def create(header, stream, *args, **kwargs)
 | 
			
		||||
        klass = case header.p_type
 | 
			
		||||
                when Constants::PT_DYNAMIC then DynamicSegment
 | 
			
		||||
                when Constants::PT_INTERP then InterpSegment
 | 
			
		||||
                when Constants::PT_LOAD then LoadSegment
 | 
			
		||||
                when Constants::PT_NOTE then NoteSegment
 | 
			
		||||
                else Segment
 | 
			
		||||
                end
 | 
			
		||||
        klass.new(header, stream, *args, **kwargs)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										211
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/structs.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/structs.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,211 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'bindata'
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Define ELF related structures in this module.
 | 
			
		||||
  #
 | 
			
		||||
  # Structures are fetched from https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h.
 | 
			
		||||
  # Use gem +bindata+ to have these structures support 32/64 bits and little/big endian simultaneously.
 | 
			
		||||
  module Structs
 | 
			
		||||
    # The base structure to define common methods.
 | 
			
		||||
    class ELFStruct < BinData::Record
 | 
			
		||||
      # DRY. Many fields have different type in different arch.
 | 
			
		||||
      CHOICE_SIZE_T = {
 | 
			
		||||
        selection: :elf_class, choices: { 32 => :uint32, 64 => :uint64 }
 | 
			
		||||
      }.freeze
 | 
			
		||||
 | 
			
		||||
      attr_accessor :elf_class # @return [Integer] 32 or 64.
 | 
			
		||||
      attr_accessor :offset # @return [Integer] The file offset of this header.
 | 
			
		||||
 | 
			
		||||
      # Records which fields have been patched.
 | 
			
		||||
      # @return [Hash{Integer => Integer}] Patches.
 | 
			
		||||
      def patches
 | 
			
		||||
        @patches ||= {}
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      class << self
 | 
			
		||||
        # Hooks the constructor.
 | 
			
		||||
        #
 | 
			
		||||
        # +BinData::Record+ doesn't allow us to override +#initialize+, so we hack +new+ here.
 | 
			
		||||
        def new(*args)
 | 
			
		||||
          # XXX: The better implementation is +new(*args, **kwargs)+, but we can't do this unless bindata changed
 | 
			
		||||
          # lib/bindata/dsl.rb#override_new_in_class to invoke +new+ with both +args+ and +kwargs+.
 | 
			
		||||
          kwargs = args.last.is_a?(Hash) ? args.last : {}
 | 
			
		||||
          offset = kwargs.delete(:offset)
 | 
			
		||||
          super.tap do |obj|
 | 
			
		||||
            obj.offset = offset
 | 
			
		||||
            obj.field_names.each do |f|
 | 
			
		||||
              m = "#{f}=".to_sym
 | 
			
		||||
              old_method = obj.singleton_method(m)
 | 
			
		||||
              obj.singleton_class.send(:undef_method, m)
 | 
			
		||||
              obj.define_singleton_method(m) do |val|
 | 
			
		||||
                org = obj.send(f)
 | 
			
		||||
                obj.patches[org.abs_offset] = ELFStruct.pack(val, org.num_bytes)
 | 
			
		||||
                old_method.call(val)
 | 
			
		||||
              end
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Gets the endianness of current class.
 | 
			
		||||
        # @return [:little, :big] The endianness.
 | 
			
		||||
        def self_endian
 | 
			
		||||
          bindata_name[-2..-1] == 'be' ? :big : :little
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Packs an integer to string.
 | 
			
		||||
        # @param [Integer] val
 | 
			
		||||
        # @param [Integer] bytes
 | 
			
		||||
        # @return [String]
 | 
			
		||||
        def pack(val, bytes)
 | 
			
		||||
          raise ArgumentError, "Not supported assign type #{val.class}" unless val.is_a?(Integer)
 | 
			
		||||
 | 
			
		||||
          number = val & ((1 << (8 * bytes)) - 1)
 | 
			
		||||
          out = []
 | 
			
		||||
          bytes.times do
 | 
			
		||||
            out << (number & 0xff)
 | 
			
		||||
            number >>= 8
 | 
			
		||||
          end
 | 
			
		||||
          out = out.pack('C*')
 | 
			
		||||
          self_endian == :little ? out : out.reverse
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # ELF header structure.
 | 
			
		||||
    class ELF_Ehdr < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      struct :e_ident do
 | 
			
		||||
        string :magic, read_length: 4
 | 
			
		||||
        int8 :ei_class
 | 
			
		||||
        int8 :ei_data
 | 
			
		||||
        int8 :ei_version
 | 
			
		||||
        int8 :ei_osabi
 | 
			
		||||
        int8 :ei_abiversion
 | 
			
		||||
        string :ei_padding, read_length: 7 # no use
 | 
			
		||||
      end
 | 
			
		||||
      uint16 :e_type
 | 
			
		||||
      uint16 :e_machine
 | 
			
		||||
      uint32 :e_version
 | 
			
		||||
      # entry point
 | 
			
		||||
      choice :e_entry, **CHOICE_SIZE_T
 | 
			
		||||
      choice :e_phoff, **CHOICE_SIZE_T
 | 
			
		||||
      choice :e_shoff, **CHOICE_SIZE_T
 | 
			
		||||
      uint32 :e_flags
 | 
			
		||||
      uint16 :e_ehsize # size of this header
 | 
			
		||||
      uint16 :e_phentsize # size of each segment
 | 
			
		||||
      uint16 :e_phnum # number of segments
 | 
			
		||||
      uint16 :e_shentsize # size of each section
 | 
			
		||||
      uint16 :e_shnum # number of sections
 | 
			
		||||
      uint16 :e_shstrndx # index of string table section
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Section header structure.
 | 
			
		||||
    class ELF_Shdr < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :sh_name
 | 
			
		||||
      uint32 :sh_type
 | 
			
		||||
      choice :sh_flags, **CHOICE_SIZE_T
 | 
			
		||||
      choice :sh_addr, **CHOICE_SIZE_T
 | 
			
		||||
      choice :sh_offset, **CHOICE_SIZE_T
 | 
			
		||||
      choice :sh_size, **CHOICE_SIZE_T
 | 
			
		||||
      uint32 :sh_link
 | 
			
		||||
      uint32 :sh_info
 | 
			
		||||
      choice :sh_addralign, **CHOICE_SIZE_T
 | 
			
		||||
      choice :sh_entsize, **CHOICE_SIZE_T
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Program header structure for 32-bit.
 | 
			
		||||
    class ELF32_Phdr < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :p_type
 | 
			
		||||
      uint32 :p_offset
 | 
			
		||||
      uint32 :p_vaddr
 | 
			
		||||
      uint32 :p_paddr
 | 
			
		||||
      uint32 :p_filesz
 | 
			
		||||
      uint32 :p_memsz
 | 
			
		||||
      uint32 :p_flags
 | 
			
		||||
      uint32 :p_align
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Program header structure for 64-bit.
 | 
			
		||||
    class ELF64_Phdr < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :p_type
 | 
			
		||||
      uint32 :p_flags
 | 
			
		||||
      uint64 :p_offset
 | 
			
		||||
      uint64 :p_vaddr
 | 
			
		||||
      uint64 :p_paddr
 | 
			
		||||
      uint64 :p_filesz
 | 
			
		||||
      uint64 :p_memsz
 | 
			
		||||
      uint64 :p_align
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Gets the class of program header according to bits.
 | 
			
		||||
    ELF_Phdr = {
 | 
			
		||||
      32 => ELF32_Phdr,
 | 
			
		||||
      64 => ELF64_Phdr
 | 
			
		||||
    }.freeze
 | 
			
		||||
 | 
			
		||||
    # Symbol structure for 32-bit.
 | 
			
		||||
    class ELF32_sym < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :st_name
 | 
			
		||||
      uint32 :st_value
 | 
			
		||||
      uint32 :st_size
 | 
			
		||||
      uint8 :st_info
 | 
			
		||||
      uint8 :st_other
 | 
			
		||||
      uint16 :st_shndx
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Symbol structure for 64-bit.
 | 
			
		||||
    class ELF64_sym < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :st_name  # Symbol name, index in string tbl
 | 
			
		||||
      uint8 :st_info   # Type and binding attributes
 | 
			
		||||
      uint8 :st_other  # No defined meaning, 0
 | 
			
		||||
      uint16 :st_shndx # Associated section index
 | 
			
		||||
      uint64 :st_value # Value of the symbol
 | 
			
		||||
      uint64 :st_size  # Associated symbol size
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get symbol header class according to bits.
 | 
			
		||||
    ELF_sym = {
 | 
			
		||||
      32 => ELF32_sym,
 | 
			
		||||
      64 => ELF64_sym
 | 
			
		||||
    }.freeze
 | 
			
		||||
 | 
			
		||||
    # Note header.
 | 
			
		||||
    class ELF_Nhdr < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      uint32 :n_namesz # Name size
 | 
			
		||||
      uint32 :n_descsz # Content size
 | 
			
		||||
      uint32 :n_type   # Content type
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Dynamic tag header.
 | 
			
		||||
    class ELF_Dyn < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      choice :d_tag, selection: :elf_class, choices: { 32 => :int32, 64 => :int64 }
 | 
			
		||||
      # This is an union type named +d_un+ in original source,
 | 
			
		||||
      # simplify it to be +d_val+ here.
 | 
			
		||||
      choice :d_val, **CHOICE_SIZE_T
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Rel header in .rel section.
 | 
			
		||||
    class ELF_Rel < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      choice :r_offset, **CHOICE_SIZE_T
 | 
			
		||||
      choice :r_info, **CHOICE_SIZE_T
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Rela header in .rela section.
 | 
			
		||||
    class ELF_Rela < ELFStruct
 | 
			
		||||
      endian :big_and_little
 | 
			
		||||
      choice :r_offset, **CHOICE_SIZE_T
 | 
			
		||||
      choice :r_info, **CHOICE_SIZE_T
 | 
			
		||||
      choice :r_addend, selection: :elf_class, choices: { 32 => :int32, 64 => :int64 }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										99
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/util.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/util.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Define some util methods.
 | 
			
		||||
  module Util
 | 
			
		||||
    # Class methods.
 | 
			
		||||
    module ClassMethods
 | 
			
		||||
      # Round up the number to be mulitple of
 | 
			
		||||
      # +2**bit+.
 | 
			
		||||
      # @param [Integer] num Number to be rounded-up.
 | 
			
		||||
      # @param [Integer] bit How many bit to be aligned.
 | 
			
		||||
      # @return [Integer] See examples.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   align(10, 1) #=> 10
 | 
			
		||||
      #   align(10, 2) #=> 12
 | 
			
		||||
      #   align(10, 3) #=> 16
 | 
			
		||||
      #   align(10, 4) #=> 16
 | 
			
		||||
      #   align(10, 5) #=> 32
 | 
			
		||||
      def align(num, bit)
 | 
			
		||||
        n = 2**bit
 | 
			
		||||
        return num if (num % n).zero?
 | 
			
		||||
 | 
			
		||||
        (num + n) & ~(n - 1)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Fetch the correct value from module +mod+.
 | 
			
		||||
      #
 | 
			
		||||
      # See {ELFTools::ELFFile#segment_by_type} for how to
 | 
			
		||||
      # use this method.
 | 
			
		||||
      # @param [Module] mod The module defined constant numbers.
 | 
			
		||||
      # @param [Integer, Symbol, String] val
 | 
			
		||||
      #   Desired value.
 | 
			
		||||
      # @return [Integer]
 | 
			
		||||
      #   Currently this method always return a value
 | 
			
		||||
      #   from {ELFTools::Constants}.
 | 
			
		||||
      def to_constant(mod, val)
 | 
			
		||||
        # Ignore the outest name.
 | 
			
		||||
        module_name = mod.name.sub('ELFTools::', '')
 | 
			
		||||
        # if val is an integer, check if exists in mod
 | 
			
		||||
        if val.is_a?(Integer)
 | 
			
		||||
          return val if mod.constants.any? { |c| mod.const_get(c) == val }
 | 
			
		||||
 | 
			
		||||
          raise ArgumentError, "No constants in #{module_name} is #{val}"
 | 
			
		||||
        end
 | 
			
		||||
        val = val.to_s.upcase
 | 
			
		||||
        prefix = module_name.split('::')[-1]
 | 
			
		||||
        val = prefix + '_' + val unless val.start_with?(prefix)
 | 
			
		||||
        val = val.to_sym
 | 
			
		||||
        raise ArgumentError, "No constants in #{module_name} named \"#{val}\"" unless mod.const_defined?(val)
 | 
			
		||||
 | 
			
		||||
        mod.const_get(val)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Read from stream until reach a null-byte.
 | 
			
		||||
      # @param [#pos=, #read] stream Streaming object
 | 
			
		||||
      # @param [Integer] offset Start from here.
 | 
			
		||||
      # @return [String] Result string will never contain null byte.
 | 
			
		||||
      # @example
 | 
			
		||||
      #   Util.cstring(File.open('/bin/cat'), 0)
 | 
			
		||||
      #   #=> "\x7FELF\x02\x01\x01"
 | 
			
		||||
      def cstring(stream, offset)
 | 
			
		||||
        stream.pos = offset
 | 
			
		||||
        # read until "\x00"
 | 
			
		||||
        ret = ''
 | 
			
		||||
        loop do
 | 
			
		||||
          c = stream.read(1)
 | 
			
		||||
          return nil if c.nil? # reach EOF
 | 
			
		||||
          break if c == "\x00"
 | 
			
		||||
 | 
			
		||||
          ret += c
 | 
			
		||||
        end
 | 
			
		||||
        ret
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Select objects from enumerator with +.type+ property
 | 
			
		||||
      # equals to +type+.
 | 
			
		||||
      #
 | 
			
		||||
      # Different from naive +Array#select+ is this method
 | 
			
		||||
      # will yield block whenever find a desired object.
 | 
			
		||||
      #
 | 
			
		||||
      # This method is used to simplify the same logic in methods
 | 
			
		||||
      # {ELFFile#sections_by_type}, {ELFFile#segments_by_type}, etc.
 | 
			
		||||
      # @param [Enumerator] enum An enumerator for further select.
 | 
			
		||||
      # @param [Object] type The type you want.
 | 
			
		||||
      # @return [Array<Object>]
 | 
			
		||||
      #   The return value will be objects in +enum+ with attribute
 | 
			
		||||
      #   +.type+ equals to +type+.
 | 
			
		||||
      def select_by_type(enum, type)
 | 
			
		||||
        enum.select do |obj|
 | 
			
		||||
          if obj.type == type
 | 
			
		||||
            yield obj if block_given?
 | 
			
		||||
            true
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    extend ClassMethods
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										6
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.2/lib/elftools/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ELFTools
 | 
			
		||||
  # Current gem version
 | 
			
		||||
  VERSION = '1.1.2'
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										10
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
# Main module of patchelf.
 | 
			
		||||
#
 | 
			
		||||
# @author david942j
 | 
			
		||||
module PatchELF
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
require 'patchelf/patcher'
 | 
			
		||||
require 'patchelf/version'
 | 
			
		||||
							
								
								
									
										148
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/cli.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/cli.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'optparse'
 | 
			
		||||
 | 
			
		||||
require 'patchelf/patcher'
 | 
			
		||||
require 'patchelf/version'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # For command line interface to parsing arguments.
 | 
			
		||||
  module CLI
 | 
			
		||||
    # Name of binary.
 | 
			
		||||
    SCRIPT_NAME = 'patchelf.rb'.freeze
 | 
			
		||||
    # CLI usage string.
 | 
			
		||||
    USAGE = format('Usage: %s <commands> FILENAME [OUTPUT_FILE]', SCRIPT_NAME).freeze
 | 
			
		||||
 | 
			
		||||
    module_function
 | 
			
		||||
 | 
			
		||||
    # Main method of CLI.
 | 
			
		||||
    # @param [Array<String>] argv
 | 
			
		||||
    #   Command line arguments.
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    # @example
 | 
			
		||||
    #   PatchELF::CLI.work(%w[--help])
 | 
			
		||||
    #   # usage message to stdout
 | 
			
		||||
    #   PatchELF::CLI.work(%w[--version])
 | 
			
		||||
    #   # version message to stdout
 | 
			
		||||
    def work(argv)
 | 
			
		||||
      @options = {
 | 
			
		||||
        set: {},
 | 
			
		||||
        print: [],
 | 
			
		||||
        needed: []
 | 
			
		||||
      }
 | 
			
		||||
      return $stdout.puts "PatchELF Version #{PatchELF::VERSION}" if argv.include?('--version')
 | 
			
		||||
      return $stdout.puts option_parser unless parse(argv)
 | 
			
		||||
 | 
			
		||||
      # Now the options are (hopefully) valid, let's process the ELF file.
 | 
			
		||||
      begin
 | 
			
		||||
        @patcher = PatchELF::Patcher.new(@options[:in_file])
 | 
			
		||||
      rescue ELFTools::ELFError, Errno::ENOENT => e
 | 
			
		||||
        return PatchELF::Logger.error(e.message)
 | 
			
		||||
      end
 | 
			
		||||
      patcher.use_rpath! if @options[:force_rpath]
 | 
			
		||||
      readonly
 | 
			
		||||
      patch_requests
 | 
			
		||||
      patcher.save(@options[:out_file])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def patcher
 | 
			
		||||
      @patcher
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def readonly
 | 
			
		||||
      @options[:print].uniq.each do |s|
 | 
			
		||||
        content = patcher.__send__(s)
 | 
			
		||||
        next if content.nil?
 | 
			
		||||
 | 
			
		||||
        s = :rpath if @options[:force_rpath] && s == :runpath
 | 
			
		||||
        $stdout.puts "#{s}: #{Array(content).join(' ')}"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def patch_requests
 | 
			
		||||
      @options[:set].each do |sym, val|
 | 
			
		||||
        patcher.__send__("#{sym}=".to_sym, val)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @options[:needed].each do |type, val|
 | 
			
		||||
        patcher.__send__("#{type}_needed".to_sym, *val)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def parse(argv)
 | 
			
		||||
      remain = option_parser.permute(argv)
 | 
			
		||||
      return false if remain.first.nil?
 | 
			
		||||
 | 
			
		||||
      @options[:in_file] = remain.first
 | 
			
		||||
      @options[:out_file] = remain[1] # can be nil
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def option_parser
 | 
			
		||||
      @option_parser ||= OptionParser.new do |opts|
 | 
			
		||||
        opts.banner = USAGE
 | 
			
		||||
 | 
			
		||||
        opts.on('--print-interpreter', '--pi', 'Show interpreter\'s name.') do
 | 
			
		||||
          @options[:print] << :interpreter
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--print-needed', '--pn', 'Show needed libraries specified in DT_NEEDED.') do
 | 
			
		||||
          @options[:print] << :needed
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--print-runpath', '--pr', 'Show the path specified in DT_RUNPATH.') do
 | 
			
		||||
          @options[:print] << :runpath
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--print-soname', '--ps', 'Show soname specified in DT_SONAME.') do
 | 
			
		||||
          @options[:print] << :soname
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--set-interpreter INTERP', '--interp INTERP', 'Set interpreter\'s name.') do |interp|
 | 
			
		||||
          @options[:set][:interpreter] = interp
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--set-needed LIB1,LIB2,LIB3', '--needed LIB1,LIB2,LIB3', Array,
 | 
			
		||||
                'Set needed libraries, this will remove all existent needed libraries.') do |needs|
 | 
			
		||||
          @options[:set][:needed] = needs
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--add-needed LIB', 'Append a new needed library.') do |lib|
 | 
			
		||||
          @options[:needed] << [:add, lib]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--remove-needed LIB', 'Remove a needed library.') do |lib|
 | 
			
		||||
          @options[:needed] << [:remove, lib]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--replace-needed LIB1,LIB2', Array, 'Replace needed library LIB1 as LIB2.') do |libs|
 | 
			
		||||
          @options[:needed] << [:replace, libs]
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--set-runpath PATH', '--runpath PATH', 'Set the path of runpath.') do |path|
 | 
			
		||||
          @options[:set][:runpath] = path
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on(
 | 
			
		||||
          '--force-rpath',
 | 
			
		||||
          'According to the ld.so docs, DT_RPATH is obsolete,',
 | 
			
		||||
          "#{SCRIPT_NAME} will always try to get/set DT_RUNPATH first.",
 | 
			
		||||
          'Use this option to force every operations related to runpath (e.g. --runpath)',
 | 
			
		||||
          'to consider \'DT_RPATH\' instead of \'DT_RUNPATH\'.'
 | 
			
		||||
        ) do
 | 
			
		||||
          @options[:force_rpath] = true
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--set-soname SONAME', '--so SONAME', 'Set name of a shared library.') do |soname|
 | 
			
		||||
          @options[:set][:soname] = soname
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        opts.on('--version', 'Show current gem\'s version.') {}
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    extend self
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										13
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/exceptions.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/exceptions.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
# encoding: ascii-8bit
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/exceptions'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Raised on an error during ELF modification.
 | 
			
		||||
  class PatchError < ELFTools::ELFError; end
 | 
			
		||||
  # Raised when Dynamic Tag is missing
 | 
			
		||||
  class MissingTagError < PatchError; end
 | 
			
		||||
  # Raised on missing Program Header(segment)
 | 
			
		||||
  class MissingSegmentError < PatchError; end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										70
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/helper.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/helper.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Helper methods for internal usage.
 | 
			
		||||
  module Helper
 | 
			
		||||
    # The size of one page.
 | 
			
		||||
    PAGE_SIZE = 0x1000
 | 
			
		||||
 | 
			
		||||
    module_function
 | 
			
		||||
 | 
			
		||||
    # Color codes for pretty print.
 | 
			
		||||
    COLOR_CODE = {
 | 
			
		||||
      esc_m: "\e[0m",
 | 
			
		||||
      info: "\e[38;5;82m", # light green
 | 
			
		||||
      warn: "\e[38;5;230m", # light yellow
 | 
			
		||||
      error: "\e[38;5;196m" # heavy red
 | 
			
		||||
    }.freeze
 | 
			
		||||
 | 
			
		||||
    # For wrapping string with color codes for prettier inspect.
 | 
			
		||||
    # @param [String] str
 | 
			
		||||
    #   Content to colorize.
 | 
			
		||||
    # @param [Symbol] type
 | 
			
		||||
    #   Specify which kind of color to use, valid symbols are defined in {.COLOR_CODE}.
 | 
			
		||||
    # @return [String]
 | 
			
		||||
    #   String that wrapped with color codes.
 | 
			
		||||
    def colorize(str, type)
 | 
			
		||||
      return str unless color_enabled?
 | 
			
		||||
 | 
			
		||||
      cc = COLOR_CODE
 | 
			
		||||
      color = cc.key?(type) ? cc[type] : ''
 | 
			
		||||
      "#{color}#{str.sub(COLOR_CODE[:esc_m], color)}#{cc[:esc_m]}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # For {#colorize} to decide if need add color codes.
 | 
			
		||||
    # @return [Boolean]
 | 
			
		||||
    def color_enabled?
 | 
			
		||||
      $stderr.tty?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @param [Integer] val
 | 
			
		||||
    # @param [Integer] align
 | 
			
		||||
    # @return [Integer]
 | 
			
		||||
    #   Aligned result.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   aligndown(0x1234)
 | 
			
		||||
    #   #=> 4096
 | 
			
		||||
    #   aligndown(0x33, 0x20)
 | 
			
		||||
    #   #=> 32
 | 
			
		||||
    #   aligndown(0x10, 0x8)
 | 
			
		||||
    #   #=> 16
 | 
			
		||||
    def aligndown(val, align = PAGE_SIZE)
 | 
			
		||||
      val - (val & (align - 1))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @param [Integer] val
 | 
			
		||||
    # @param [Integer] align
 | 
			
		||||
    # @return [Integer]
 | 
			
		||||
    #   Aligned result.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   alignup(0x1234)
 | 
			
		||||
    #   #=> 8192
 | 
			
		||||
    #   alignup(0x33, 0x20)
 | 
			
		||||
    #   #=> 64
 | 
			
		||||
    #   alignup(0x10, 0x8)
 | 
			
		||||
    #   #=> 16
 | 
			
		||||
    def alignup(val, align = PAGE_SIZE)
 | 
			
		||||
      (val & (align - 1)).zero? ? val : (aligndown(val, align) + align)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										25
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/logger.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/logger.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'logger'
 | 
			
		||||
 | 
			
		||||
require 'patchelf/helper'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # A logger for internal usage.
 | 
			
		||||
  module Logger
 | 
			
		||||
    module_function
 | 
			
		||||
 | 
			
		||||
    @logger = ::Logger.new($stderr).tap do |log|
 | 
			
		||||
      log.formatter = proc do |severity, _datetime, _progname, msg|
 | 
			
		||||
        "[#{PatchELF::Helper.colorize(severity, severity.downcase.to_sym)}] #{msg}\n"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    %i[info warn error].each do |sym|
 | 
			
		||||
      define_method(sym) do |msg|
 | 
			
		||||
        @logger.__send__(sym, msg)
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/mm.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/mm.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,186 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'patchelf/helper'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Memory management, provides malloc/free to allocate LOAD segments.
 | 
			
		||||
  # @private
 | 
			
		||||
  class MM
 | 
			
		||||
    attr_reader :extend_size # @return [Integer] The size extended.
 | 
			
		||||
    attr_reader :threshold # @return [Integer] Where the file start to be extended.
 | 
			
		||||
 | 
			
		||||
    # Instantiate a {MM} object.
 | 
			
		||||
    # @param [ELFTools::ELFFile] elf
 | 
			
		||||
    def initialize(elf)
 | 
			
		||||
      @elf = elf
 | 
			
		||||
      @request = []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @param [Integer] size
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    # @yieldparam [Integer] off
 | 
			
		||||
    # @yieldparam [Integer] vaddr
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    #   One can only do the following things in the block:
 | 
			
		||||
    #   1. Set ELF headers' attributes (with ELFTools)
 | 
			
		||||
    #   2. Invoke {Saver#inline_patch}
 | 
			
		||||
    def malloc(size, &block)
 | 
			
		||||
      raise ArgumentError, 'malloc\'s size most be positive.' if size <= 0
 | 
			
		||||
 | 
			
		||||
      @request << [size, block]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Let the malloc / free requests be effective.
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def dispatch!
 | 
			
		||||
      return if @request.empty?
 | 
			
		||||
 | 
			
		||||
      @request_size = @request.map(&:first).inject(0, :+)
 | 
			
		||||
      # The malloc-ed area must be 'rw-' since the dynamic table will be modified during runtime.
 | 
			
		||||
      # Find all LOADs and calculate their f-gaps and m-gaps.
 | 
			
		||||
      # We prefer f-gap since it doesn't need move the whole binaries.
 | 
			
		||||
      # 1. Find if any f-gap has enough size, and one of the LOAD next to it is 'rw-'.
 | 
			
		||||
      #   - expand (forwardlly), only need to change the attribute of LOAD.
 | 
			
		||||
      # 2. Do 1. again but consider m-gaps instead.
 | 
			
		||||
      #   - expand (forwardlly), need to modify all section headers.
 | 
			
		||||
      # 3. We have to create a new LOAD, now we need to expand the first LOAD for putting new segment header.
 | 
			
		||||
 | 
			
		||||
      # First of all we check if there're less than two LOADs.
 | 
			
		||||
      abnormal_elf('No LOAD segment found, not an executable.') if load_segments.empty?
 | 
			
		||||
      # TODO: Handle only one LOAD. (be careful if memsz > filesz)
 | 
			
		||||
 | 
			
		||||
      fgap_method || mgap_method || new_load_method
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Query if extended.
 | 
			
		||||
    # @return [Boolean]
 | 
			
		||||
    def extended?
 | 
			
		||||
      defined?(@threshold)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get correct offset after the extension.
 | 
			
		||||
    #
 | 
			
		||||
    # @param [Integer] off
 | 
			
		||||
    # @return [Integer]
 | 
			
		||||
    #   Shifted offset.
 | 
			
		||||
    def extended_offset(off)
 | 
			
		||||
      return off unless defined?(@threshold)
 | 
			
		||||
      return off if off < @threshold
 | 
			
		||||
 | 
			
		||||
      off + @extend_size
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def fgap_method
 | 
			
		||||
      idx = find_gap { |prv, nxt| nxt.file_head - prv.file_tail }
 | 
			
		||||
      return false if idx.nil?
 | 
			
		||||
 | 
			
		||||
      loads = load_segments
 | 
			
		||||
      # prefer extend backwardly
 | 
			
		||||
      return extend_backward(loads[idx - 1]) if writable?(loads[idx - 1])
 | 
			
		||||
 | 
			
		||||
      extend_forward(loads[idx])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def extend_backward(seg, size = @request_size)
 | 
			
		||||
      invoke_callbacks(seg, seg.file_tail)
 | 
			
		||||
      seg.header.p_filesz += size
 | 
			
		||||
      seg.header.p_memsz += size
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def extend_forward(seg, size = @request_size)
 | 
			
		||||
      seg.header.p_offset -= size
 | 
			
		||||
      seg.header.p_vaddr -= size
 | 
			
		||||
      seg.header.p_filesz += size
 | 
			
		||||
      seg.header.p_memsz += size
 | 
			
		||||
      invoke_callbacks(seg, seg.file_head)
 | 
			
		||||
      true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def mgap_method
 | 
			
		||||
      # |  1  | |  2  |
 | 
			
		||||
      # |  1  |        |  2  |
 | 
			
		||||
      #=>
 | 
			
		||||
      # |  1      | |  2  |
 | 
			
		||||
      # |  1      |    |  2  |
 | 
			
		||||
      idx = find_gap(check_sz: false) { |prv, nxt| PatchELF::Helper.aligndown(nxt.mem_head) - prv.mem_tail }
 | 
			
		||||
      return false if idx.nil?
 | 
			
		||||
 | 
			
		||||
      loads = load_segments
 | 
			
		||||
      @threshold = loads[idx].file_head
 | 
			
		||||
      @extend_size = PatchELF::Helper.alignup(@request_size)
 | 
			
		||||
      shift_attributes
 | 
			
		||||
      # prefer backward than forward
 | 
			
		||||
      return extend_backward(loads[idx - 1]) if writable?(loads[idx - 1])
 | 
			
		||||
 | 
			
		||||
      # note: loads[idx].file_head has been changed in shift_attributes
 | 
			
		||||
      extend_forward(loads[idx], @extend_size)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def find_gap(check_sz: true)
 | 
			
		||||
      loads = load_segments
 | 
			
		||||
      loads.each_with_index do |l, i|
 | 
			
		||||
        next if i.zero?
 | 
			
		||||
        next unless writable?(l) || writable?(loads[i - 1])
 | 
			
		||||
 | 
			
		||||
        sz = yield(loads[i - 1], l)
 | 
			
		||||
        abnormal_elf('LOAD segments are out of order.') if check_sz && sz.negative?
 | 
			
		||||
        next unless sz >= @request_size
 | 
			
		||||
 | 
			
		||||
        return i
 | 
			
		||||
      end
 | 
			
		||||
      nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # TODO
 | 
			
		||||
    def new_load_method
 | 
			
		||||
      raise NotImplementedError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def writable?(seg)
 | 
			
		||||
      seg.readable? && seg.writable?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # For all attributes >= threshold, += offset
 | 
			
		||||
    def shift_attributes
 | 
			
		||||
      # ELFHeader->section_header
 | 
			
		||||
      # Sections:
 | 
			
		||||
      #   all
 | 
			
		||||
      # Segments:
 | 
			
		||||
      #   all
 | 
			
		||||
      # XXX: will be buggy if someday the number of segments can be changed.
 | 
			
		||||
 | 
			
		||||
      # Bottom-up
 | 
			
		||||
      @elf.each_sections do |sec|
 | 
			
		||||
        sec.header.sh_offset += extend_size if sec.header.sh_offset >= threshold
 | 
			
		||||
      end
 | 
			
		||||
      @elf.each_segments do |seg|
 | 
			
		||||
        next unless seg.header.p_offset >= threshold
 | 
			
		||||
 | 
			
		||||
        seg.header.p_offset += extend_size
 | 
			
		||||
        # We have to change align of LOAD segment since ld.so checks it.
 | 
			
		||||
        seg.header.p_align = Helper::PAGE_SIZE if seg.is_a?(ELFTools::Segments::LoadSegment)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @elf.header.e_shoff += extend_size if @elf.header.e_shoff >= threshold
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def load_segments
 | 
			
		||||
      @elf.segments_by_type(:load)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def invoke_callbacks(seg, start)
 | 
			
		||||
      cur = start
 | 
			
		||||
      @request.each do |sz, block|
 | 
			
		||||
        block.call(cur, seg.offset_to_vma(cur))
 | 
			
		||||
        cur += sz
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def abnormal_elf(msg)
 | 
			
		||||
      raise ArgumentError, msg
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										243
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/patcher.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/patcher.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,243 @@
 | 
			
		||||
# encoding: ascii-8bit
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/elf_file'
 | 
			
		||||
 | 
			
		||||
require 'patchelf/exceptions'
 | 
			
		||||
require 'patchelf/logger'
 | 
			
		||||
require 'patchelf/saver'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Class to handle all patching things.
 | 
			
		||||
  class Patcher
 | 
			
		||||
    # @!macro [new] note_apply
 | 
			
		||||
    #   @note This setting will be saved after {#save} being invoked.
 | 
			
		||||
 | 
			
		||||
    attr_reader :elf # @return [ELFTools::ELFFile] ELF parser object.
 | 
			
		||||
 | 
			
		||||
    # Instantiate a {Patcher} object.
 | 
			
		||||
    # @param [String] filename
 | 
			
		||||
    #   Filename of input ELF.
 | 
			
		||||
    # @param [Boolean] logging
 | 
			
		||||
    #   *deprecated*: use +on_error+ instead
 | 
			
		||||
    # @param [:log, :silent, :exception] on_error
 | 
			
		||||
    #   action when the desired segment/tag field isn't present
 | 
			
		||||
    #     :log = logs to stderr
 | 
			
		||||
    #     :exception = raise exception related to the error
 | 
			
		||||
    #     :silent = ignore the errors
 | 
			
		||||
    def initialize(filename, on_error: :log, logging: true)
 | 
			
		||||
      @in_file = filename
 | 
			
		||||
      @elf = ELFTools::ELFFile.new(File.open(filename))
 | 
			
		||||
      @set = {}
 | 
			
		||||
      @rpath_sym = :runpath
 | 
			
		||||
      @on_error = !logging ? :exception : on_error
 | 
			
		||||
 | 
			
		||||
      on_error_syms = %i[exception log silent]
 | 
			
		||||
      raise ArgumentError, "on_error must be one of #{on_error_syms}" unless on_error_syms.include?(@on_error)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [String?]
 | 
			
		||||
    #   Get interpreter's name.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   PatchELF::Patcher.new('/bin/ls').interpreter
 | 
			
		||||
    #   #=> "/lib64/ld-linux-x86-64.so.2"
 | 
			
		||||
    def interpreter
 | 
			
		||||
      @set[:interpreter] || interpreter_
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set interpreter's name.
 | 
			
		||||
    #
 | 
			
		||||
    # If the input ELF has no existent interpreter,
 | 
			
		||||
    # this method will show a warning and has no effect.
 | 
			
		||||
    # @param [String] interp
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def interpreter=(interp)
 | 
			
		||||
      return if interpreter_.nil? # will also show warning if there's no interp segment.
 | 
			
		||||
 | 
			
		||||
      @set[:interpreter] = interp
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get needed libraries.
 | 
			
		||||
    # @return [Array<String>]
 | 
			
		||||
    # @example
 | 
			
		||||
    #   patcher = PatchELF::Patcher.new('/bin/ls')
 | 
			
		||||
    #   patcher.needed
 | 
			
		||||
    #   #=> ["libselinux.so.1", "libc.so.6"]
 | 
			
		||||
    def needed
 | 
			
		||||
      @set[:needed] || needed_
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set needed libraries.
 | 
			
		||||
    # @param [Array<String>] needs
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def needed=(needs)
 | 
			
		||||
      @set[:needed] = needs
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Add the needed library.
 | 
			
		||||
    # @param [String] need
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def add_needed(need)
 | 
			
		||||
      @set[:needed] ||= needed_
 | 
			
		||||
      @set[:needed] << need
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Remove the needed library.
 | 
			
		||||
    # @param [String] need
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def remove_needed(need)
 | 
			
		||||
      @set[:needed] ||= needed_
 | 
			
		||||
      @set[:needed].delete(need)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Replace needed library +src+ with +tar+.
 | 
			
		||||
    #
 | 
			
		||||
    # @param [String] src
 | 
			
		||||
    #   Library to be replaced.
 | 
			
		||||
    # @param [String] tar
 | 
			
		||||
    #   Library replace with.
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def replace_needed(src, tar)
 | 
			
		||||
      @set[:needed] ||= needed_
 | 
			
		||||
      @set[:needed].map! { |v| v == src ? tar : v }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get the soname of a shared library.
 | 
			
		||||
    # @return [String?] The name.
 | 
			
		||||
    # @example
 | 
			
		||||
    #   patcher = PatchELF::Patcher.new('/bin/ls')
 | 
			
		||||
    #   patcher.soname
 | 
			
		||||
    #   # [WARN] Entry DT_SONAME not found, not a shared library?
 | 
			
		||||
    #   #=> nil
 | 
			
		||||
    # @example
 | 
			
		||||
    #   PatchELF::Patcher.new('/lib/x86_64-linux-gnu/libc.so.6').soname
 | 
			
		||||
    #   #=> "libc.so.6"
 | 
			
		||||
    def soname
 | 
			
		||||
      @set[:soname] || soname_
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set soname.
 | 
			
		||||
    #
 | 
			
		||||
    # If the input ELF is not a shared library with a soname,
 | 
			
		||||
    # this method will show a warning and has no effect.
 | 
			
		||||
    # @param [String] name
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def soname=(name)
 | 
			
		||||
      return if soname_.nil?
 | 
			
		||||
 | 
			
		||||
      @set[:soname] = name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get runpath.
 | 
			
		||||
    # @return [String?]
 | 
			
		||||
    def runpath
 | 
			
		||||
      @set[@rpath_sym] || runpath_(@rpath_sym)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Get rpath
 | 
			
		||||
    # return [String?]
 | 
			
		||||
    def rpath
 | 
			
		||||
      @set[:rpath] || runpath_(:rpath)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set rpath
 | 
			
		||||
    #
 | 
			
		||||
    # Modify / set DT_RPATH of the given ELF.
 | 
			
		||||
    # similar to runpath= except DT_RPATH is modifed/created in DYNAMIC segment.
 | 
			
		||||
    # @param [String] rpath
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def rpath=(rpath)
 | 
			
		||||
      @set[:rpath] = rpath
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set runpath.
 | 
			
		||||
    #
 | 
			
		||||
    # If DT_RUNPATH is not presented in the input ELF,
 | 
			
		||||
    # a new DT_RUNPATH attribute will be inserted into the DYNAMIC segment.
 | 
			
		||||
    # @param [String] runpath
 | 
			
		||||
    # @macro note_apply
 | 
			
		||||
    def runpath=(runpath)
 | 
			
		||||
      @set[@rpath_sym] = runpath
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set all operations related to DT_RUNPATH to use DT_RPATH.
 | 
			
		||||
    # @return [self]
 | 
			
		||||
    def use_rpath!
 | 
			
		||||
      @rpath_sym = :rpath
 | 
			
		||||
      self
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Save the patched ELF as +out_file+.
 | 
			
		||||
    # @param [String?] out_file
 | 
			
		||||
    #   If +out_file+ is +nil+, the original input file will be modified.
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def save(out_file = nil)
 | 
			
		||||
      # If nothing is modified, return directly.
 | 
			
		||||
      return if out_file.nil? && !dirty?
 | 
			
		||||
 | 
			
		||||
      out_file ||= @in_file
 | 
			
		||||
      saver = PatchELF::Saver.new(@in_file, out_file, @set)
 | 
			
		||||
 | 
			
		||||
      saver.save!
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def log_or_raise(msg, exception = PatchELF::PatchError)
 | 
			
		||||
      raise exception, msg if @on_error == :exception
 | 
			
		||||
 | 
			
		||||
      PatchELF::Logger.warn(msg) if @on_error == :log
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def interpreter_
 | 
			
		||||
      segment = @elf.segment_by_type(:interp)
 | 
			
		||||
      return log_or_raise 'No interpreter found.', PatchELF::MissingSegmentError if segment.nil?
 | 
			
		||||
 | 
			
		||||
      segment.interp_name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [Array<String>]
 | 
			
		||||
    def needed_
 | 
			
		||||
      segment = dynamic_or_log
 | 
			
		||||
      return if segment.nil?
 | 
			
		||||
 | 
			
		||||
      segment.tags_by_type(:needed).map(&:name)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [String?]
 | 
			
		||||
    def runpath_(rpath_sym = :runpath)
 | 
			
		||||
      tag_name_or_log(rpath_sym, "Entry DT_#{rpath_sym.to_s.upcase} not found.")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [String?]
 | 
			
		||||
    def soname_
 | 
			
		||||
      tag_name_or_log(:soname, 'Entry DT_SONAME not found, not a shared library?')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [Boolean]
 | 
			
		||||
    def dirty?
 | 
			
		||||
      @set.any?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def tag_name_or_log(type, log_msg)
 | 
			
		||||
      segment = dynamic_or_log
 | 
			
		||||
      return if segment.nil?
 | 
			
		||||
 | 
			
		||||
      tag = segment.tag_by_type(type)
 | 
			
		||||
      return log_or_raise log_msg, PatchELF::MissingTagError if tag.nil?
 | 
			
		||||
 | 
			
		||||
      tag.name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def dynamic_or_log
 | 
			
		||||
      @elf.segment_by_type(:dynamic).tap do |s|
 | 
			
		||||
        if s.nil?
 | 
			
		||||
          log_or_raise 'DYNAMIC segment not found, might be a statically-linked ELF?', PatchELF::MissingSegmentError
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										285
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/saver.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/saver.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,285 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require 'elftools/constants'
 | 
			
		||||
require 'elftools/elf_file'
 | 
			
		||||
require 'elftools/structs'
 | 
			
		||||
require 'elftools/util'
 | 
			
		||||
require 'fileutils'
 | 
			
		||||
 | 
			
		||||
require 'patchelf/mm'
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Internal use only.
 | 
			
		||||
  #
 | 
			
		||||
  # For {Patcher} to do patching things and save to file.
 | 
			
		||||
  # @private
 | 
			
		||||
  class Saver
 | 
			
		||||
    attr_reader :in_file # @return [String] Input filename.
 | 
			
		||||
    attr_reader :out_file # @return [String] Output filename.
 | 
			
		||||
 | 
			
		||||
    # Instantiate a {Saver} object.
 | 
			
		||||
    # @param [String] in_file
 | 
			
		||||
    # @param [String] out_file
 | 
			
		||||
    # @param [{Symbol => String, Array}] set
 | 
			
		||||
    def initialize(in_file, out_file, set)
 | 
			
		||||
      @in_file = in_file
 | 
			
		||||
      @out_file = out_file
 | 
			
		||||
      @set = set
 | 
			
		||||
      # [{Integer => String}]
 | 
			
		||||
      @inline_patch = {}
 | 
			
		||||
      @elf = ELFTools::ELFFile.new(File.open(in_file))
 | 
			
		||||
      @mm = PatchELF::MM.new(@elf)
 | 
			
		||||
      @strtab_extend_requests = []
 | 
			
		||||
      @append_dyn = []
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [void]
 | 
			
		||||
    def save!
 | 
			
		||||
      # In this method we assume all attributes that should exist do exist.
 | 
			
		||||
      # e.g. DT_INTERP, DT_DYNAMIC. These should have been checked in the patcher.
 | 
			
		||||
      patch_interpreter
 | 
			
		||||
      patch_dynamic
 | 
			
		||||
 | 
			
		||||
      @mm.dispatch!
 | 
			
		||||
 | 
			
		||||
      FileUtils.cp(in_file, out_file) if out_file != in_file
 | 
			
		||||
      patch_out(@out_file)
 | 
			
		||||
      # Let output file have the same permission as input.
 | 
			
		||||
      FileUtils.chmod(File.stat(in_file).mode, out_file)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
 | 
			
		||||
    def patch_interpreter
 | 
			
		||||
      return if @set[:interpreter].nil?
 | 
			
		||||
 | 
			
		||||
      new_interp = @set[:interpreter] + "\x00"
 | 
			
		||||
      old_interp = @elf.segment_by_type(:interp).interp_name + "\x00"
 | 
			
		||||
      return if old_interp == new_interp
 | 
			
		||||
 | 
			
		||||
      # These headers must be found here but not in the proc.
 | 
			
		||||
      seg_header = @elf.segment_by_type(:interp).header
 | 
			
		||||
      sec_header = section_header('.interp')
 | 
			
		||||
 | 
			
		||||
      patch = proc do |off, vaddr|
 | 
			
		||||
        # Register an inline patching
 | 
			
		||||
        inline_patch(off, new_interp)
 | 
			
		||||
 | 
			
		||||
        # The patching feature of ELFTools
 | 
			
		||||
        seg_header.p_offset = off
 | 
			
		||||
        seg_header.p_vaddr = seg_header.p_paddr = vaddr
 | 
			
		||||
        seg_header.p_filesz = seg_header.p_memsz = new_interp.size
 | 
			
		||||
 | 
			
		||||
        if sec_header
 | 
			
		||||
          sec_header.sh_offset = off
 | 
			
		||||
          sec_header.sh_size = new_interp.size
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if new_interp.size <= old_interp.size
 | 
			
		||||
        # easy case
 | 
			
		||||
        patch.call(seg_header.p_offset.to_i, seg_header.p_vaddr.to_i)
 | 
			
		||||
      else
 | 
			
		||||
        # hard case, we have to request a new LOAD area
 | 
			
		||||
        @mm.malloc(new_interp.size, &patch)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def patch_dynamic
 | 
			
		||||
      # We never do inline patching on strtab's string.
 | 
			
		||||
      # 1. Search if there's useful string exists
 | 
			
		||||
      #   - only need header patching
 | 
			
		||||
      # 2. Append a new string to the strtab.
 | 
			
		||||
      #   - register strtab extension
 | 
			
		||||
      dynamic.tags # HACK, force @tags to be defined
 | 
			
		||||
      patch_soname if @set[:soname]
 | 
			
		||||
      patch_runpath if @set[:runpath]
 | 
			
		||||
      patch_runpath(:rpath) if @set[:rpath]
 | 
			
		||||
      patch_needed if @set[:needed]
 | 
			
		||||
      malloc_strtab!
 | 
			
		||||
      expand_dynamic!
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def patch_soname
 | 
			
		||||
      # The tag must exist.
 | 
			
		||||
      so_tag = dynamic.tag_by_type(:soname)
 | 
			
		||||
      reg_str_table(@set[:soname]) do |idx|
 | 
			
		||||
        so_tag.header.d_val = idx
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def patch_runpath(sym = :runpath)
 | 
			
		||||
      tag = dynamic.tag_by_type(sym)
 | 
			
		||||
      tag = tag.nil? ? lazy_dyn(sym) : tag.header
 | 
			
		||||
      reg_str_table(@set[sym]) do |idx|
 | 
			
		||||
        tag.d_val = idx
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # To mark a not-using tag
 | 
			
		||||
    IGNORE = ELFTools::Constants::DT_LOOS
 | 
			
		||||
    def patch_needed
 | 
			
		||||
      original_needs = dynamic.tags_by_type(:needed)
 | 
			
		||||
      @set[:needed].uniq!
 | 
			
		||||
      # 3 sets:
 | 
			
		||||
      # 1. in original and in needs - remain unchanged
 | 
			
		||||
      # 2. in original but not in needs - remove
 | 
			
		||||
      # 3. not in original and in needs - append
 | 
			
		||||
      original_needs.each do |n|
 | 
			
		||||
        next if @set[:needed].include?(n.name)
 | 
			
		||||
 | 
			
		||||
        n.header.d_tag = IGNORE # temporarily mark
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      extra = @set[:needed] - original_needs.map(&:name)
 | 
			
		||||
      original_needs.each do |n|
 | 
			
		||||
        break if extra.empty?
 | 
			
		||||
        next if n.header.d_tag != IGNORE
 | 
			
		||||
 | 
			
		||||
        n.header.d_tag = ELFTools::Constants::DT_NEEDED
 | 
			
		||||
        reg_str_table(extra.shift) { |idx| n.header.d_val = idx }
 | 
			
		||||
      end
 | 
			
		||||
      return if extra.empty?
 | 
			
		||||
 | 
			
		||||
      # no spaces, need append
 | 
			
		||||
      extra.each do |name|
 | 
			
		||||
        tag = lazy_dyn(:needed)
 | 
			
		||||
        reg_str_table(name) { |idx| tag.d_val = idx }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Create a temp tag header.
 | 
			
		||||
    # @return [ELFTools::Structs::ELF_Dyn]
 | 
			
		||||
    def lazy_dyn(sym)
 | 
			
		||||
      ELFTools::Structs::ELF_Dyn.new(endian: @elf.endian).tap do |dyn|
 | 
			
		||||
        @append_dyn << dyn
 | 
			
		||||
        dyn.elf_class = @elf.elf_class
 | 
			
		||||
        dyn.d_tag = ELFTools::Util.to_constant(ELFTools::Constants::DT, sym)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def expand_dynamic!
 | 
			
		||||
      return if @append_dyn.empty?
 | 
			
		||||
 | 
			
		||||
      dyn_sec = section_header('.dynamic')
 | 
			
		||||
      total = dynamic.tags.map(&:header)
 | 
			
		||||
      # the last must be a null-tag
 | 
			
		||||
      total = total[0..-2] + @append_dyn + [total.last]
 | 
			
		||||
      bytes = total.first.num_bytes * total.size
 | 
			
		||||
      @mm.malloc(bytes) do |off, vaddr|
 | 
			
		||||
        inline_patch(off, total.map(&:to_binary_s).join)
 | 
			
		||||
        dynamic.header.p_offset = off
 | 
			
		||||
        dynamic.header.p_vaddr = dynamic.header.p_paddr = vaddr
 | 
			
		||||
        dynamic.header.p_filesz = dynamic.header.p_memsz = bytes
 | 
			
		||||
        if dyn_sec
 | 
			
		||||
          dyn_sec.sh_offset = off
 | 
			
		||||
          dyn_sec.sh_addr = vaddr
 | 
			
		||||
          dyn_sec.sh_size = bytes
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def malloc_strtab!
 | 
			
		||||
      return if @strtab_extend_requests.empty?
 | 
			
		||||
 | 
			
		||||
      strtab = dynamic.tag_by_type(:strtab)
 | 
			
		||||
      # Process registered requests
 | 
			
		||||
      need_size = strtab_string.size + @strtab_extend_requests.reduce(0) { |sum, (str, _)| sum + str.size + 1 }
 | 
			
		||||
      dynstr = section_header('.dynstr')
 | 
			
		||||
      @mm.malloc(need_size) do |off, vaddr|
 | 
			
		||||
        new_str = strtab_string + @strtab_extend_requests.map(&:first).join("\x00") + "\x00"
 | 
			
		||||
        inline_patch(off, new_str)
 | 
			
		||||
        cur = strtab_string.size
 | 
			
		||||
        @strtab_extend_requests.each do |str, block|
 | 
			
		||||
          block.call(cur)
 | 
			
		||||
          cur += str.size + 1
 | 
			
		||||
        end
 | 
			
		||||
        # Now patching strtab header
 | 
			
		||||
        strtab.header.d_val = vaddr
 | 
			
		||||
        # We also need to patch dynstr to let readelf have correct output.
 | 
			
		||||
        if dynstr
 | 
			
		||||
          dynstr.sh_size = new_str.size
 | 
			
		||||
          dynstr.sh_offset = off
 | 
			
		||||
          dynstr.sh_addr = vaddr
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @param [String] str
 | 
			
		||||
    # @yieldparam [Integer] idx
 | 
			
		||||
    # @yieldreturn [void]
 | 
			
		||||
    def reg_str_table(str, &block)
 | 
			
		||||
      idx = strtab_string.index(str + "\x00")
 | 
			
		||||
      # Request string is already exist
 | 
			
		||||
      return yield idx if idx
 | 
			
		||||
 | 
			
		||||
      # Record the request
 | 
			
		||||
      @strtab_extend_requests << [str, block]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def strtab_string
 | 
			
		||||
      return @strtab_string if defined?(@strtab_string)
 | 
			
		||||
 | 
			
		||||
      # TODO: handle no strtab exists..
 | 
			
		||||
      offset = @elf.offset_from_vma(dynamic.tag_by_type(:strtab).value)
 | 
			
		||||
      # This is a little tricky since no length information is stored in the tag.
 | 
			
		||||
      # We first get the file offset of the string then 'guess' where the end is.
 | 
			
		||||
      @elf.stream.pos = offset
 | 
			
		||||
      @strtab_string = +''
 | 
			
		||||
      loop do
 | 
			
		||||
        c = @elf.stream.read(1)
 | 
			
		||||
        break unless c =~ /\x00|[[:print:]]/
 | 
			
		||||
 | 
			
		||||
        @strtab_string << c
 | 
			
		||||
      end
 | 
			
		||||
      @strtab_string
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # This can only be used for patching interpreter's name
 | 
			
		||||
    # or set strings in a malloc-ed area.
 | 
			
		||||
    # i.e. NEVER intend to change the string defined in strtab
 | 
			
		||||
    def inline_patch(off, str)
 | 
			
		||||
      @inline_patch[off] = str
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Modify the out_file according to registered patches.
 | 
			
		||||
    def patch_out(out_file)
 | 
			
		||||
      File.open(out_file, 'r+') do |f|
 | 
			
		||||
        if @mm.extended?
 | 
			
		||||
          original_head = @mm.threshold
 | 
			
		||||
          extra = {}
 | 
			
		||||
          # Copy all data after the second load
 | 
			
		||||
          @elf.stream.pos = original_head
 | 
			
		||||
          extra[original_head + @mm.extend_size] = @elf.stream.read # read to end
 | 
			
		||||
          # zero out the 'gap' we created
 | 
			
		||||
          extra[original_head] = "\x00" * @mm.extend_size
 | 
			
		||||
          extra.each do |pos, str|
 | 
			
		||||
            f.pos = pos
 | 
			
		||||
            f.write(str)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        @elf.patches.each do |pos, str|
 | 
			
		||||
          f.pos = @mm.extended_offset(pos)
 | 
			
		||||
          f.write(str)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        @inline_patch.each do |pos, str|
 | 
			
		||||
          f.pos = pos
 | 
			
		||||
          f.write(str)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return [ELFTools::Sections::Section?]
 | 
			
		||||
    def section_header(name)
 | 
			
		||||
      sec = @elf.section_by_name(name)
 | 
			
		||||
      return if sec.nil?
 | 
			
		||||
 | 
			
		||||
      sec.header
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def dynamic
 | 
			
		||||
      @dynamic ||= @elf.segment_by_type(:dynamic)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										6
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/patchelf-1.2.0/lib/patchelf/version.rb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module PatchELF
 | 
			
		||||
  # Current gem version.
 | 
			
		||||
  VERSION = '1.2.0'.freeze
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user