class Undll32::Buffer

represents a string/struct. Buffer.new({ :x => :L, :y => 4 }) Buffer.new([ :L, 4 ]) Buffer.new(:L) Buffer.new(4) buffer.buffer => “0000” buffer.unpack => 0

Attributes

struct[RW]

Public Class Methods

from(code) click to toggle source
# File lib/undll32.rb, line 250
def self.from code
  return from_array(code) if code.start_with?('[')
  return from_size(code) if code.start_with?(':')
  code = "{#{code}}" unless code.start_with?('{')
  return from_struct(code)
end
from_array(code) click to toggle source
# File lib/undll32.rb, line 165
def self.from_array code
  unless code =~ /^\[[CSLQ]+\]$/
    raise ArgumentError, "expected [CSLQ], got #{code}"
  end
  return new(code[1..-2].chars.map(&:to_sym))
end
from_size(code) click to toggle source
# File lib/undll32.rb, line 172
def self.from_size code
  m = code.match(/^\:(?<size>[^=]+)=?(?<value>.+)?$/)
  if m.nil?
    raise ArgumentError, "expected <number> or CSLQ, got #{code}"
  end
  if m[:size] =~ /^[CSLQ]+$/
    s = m[:size].chars.map(&:to_sym)
    if s.size == 1
      return new(s[0]).tap { |b| b.load(m[:value].to_i) if m[:value] }
    else
      b = new(s)
      b.load(m[:value].split(':').map(&:to_i)) if m[:value]
      return b
    end
  end
  if (n = m[:size].to_i)
    return new(n).tap { |b| b.load(m[:value]) if m[:value] }
  end
  raise ArgumentError, "expected <number> or CSLQ, got #{code}"
end
from_struct(code) click to toggle source
# File lib/undll32.rb, line 198
def self.from_struct code
  default = {}
  # code := '{' [name] [:type] [=value] [,...] '}'
  env, keys, key = [], [], ''
  seq = code.scan /\w+|\:[[:digit:]]+|\:[CSLQ:]+|=[^,\}]+|./
  ret = while (token = seq.shift)
    case token[0]
    when '{'
      keys.push(key.to_sym) unless key.empty?
      env.push({})
      key = ''
    when '}'
      env[-1][key.to_sym] = :L unless key.empty?
      x = env.pop
      break x if env.empty?
      env[-1][keys.pop] = x
      key = ''
    when ':'
      token << seq.shift if seq.first&.start_with?('=')
      b = from_size(token)
      key = next_placeholder if key.empty?
      env[-1][key.to_sym] = b.struct
      d = default
      keys.each { |k| d[k] ||= {}; d = d[k] }
      d[key.to_sym] = b.unpack
      key = ''
    when '='
      e = token[1..-1]
      e = Integer(e) rescue nil
      type = Integer === e ? :L : (e.length + 1)
      env[-1][key.to_sym] = type
      d = default
      keys.each { |k| d[k] ||= {}; d = d[k] }
      if Integer === type
        e = "\"#{e}\"".undump rescue e.undump
      end
      d[key.to_sym] = e
      key = ''
    when ','
      next if key.empty?
      env[-1][key.to_sym] = :L
      key = ''
    else
      key << token
    end
  end
  if ret.nil?
    raise ArgumentError, 'expected }, got end-of-input'
  end
  new(ret).tap { |b| b.load(default) }
end
new(struct) click to toggle source
# File lib/undll32.rb, line 64
def initialize struct
  case struct
  when Hash, Array, Symbol, Integer
    @struct = struct
  else
    raise ArgumentError, "expected hash, array, sym, int, got #{struct}"
  end
end
next_placeholder() click to toggle source
# File lib/undll32.rb, line 193
def self.next_placeholder
  @_placeholder_counter ||= 0
  "__#{@_placeholder_counter += 1}__"
end

Public Instance Methods

_buffer(x) click to toggle source
# File lib/undll32.rb, line 144
def _buffer x
  case x
  when Integer
    [].pack("x#{x}")
  when Symbol
    n = { C: 1, S: 2, L: 4, Q: 8 }[x]
    if n.nil?
      raise ArgumentError, "expected CSLQ, got #{x}"
    end
    [].pack("x#{n}")
  when Array
    x.map { |e| _buffer e }.join
  when Hash
    _buffer x.values
  else
    raise ArgumentError, "expected hash, array, sym, int, got #{x}"
  end
ensure
  $@.shift if $@
end
_load(x, v) click to toggle source
# File lib/undll32.rb, line 88
def _load x, v
  case x
  when Integer
    return @_i += x if v.nil?
    unless String === v
      raise ArgumentError, "expected str, got #{v}"
    end
    x = [x, v.length].min
    buffer[(@_i += x) - x, x] = v[0, x]
  when Symbol
    n = { C: 1, S: 2, L: 4, Q: 8 }[x]
    if n.nil?
      raise ArgumentError, "expected CSLQ, got #{x}"
    end
    return @_i += n if v.nil?
    unless Integer === v
      raise ArgumentError, "expected int, got #{v}"
    end
    buffer[(@_i += n) - n, n] = [v].pack("#{x}")
  when Array
    return x.each { |a| _load a, nil } if v.nil?
    unless Array === v and v.size == x.size
      raise ArgumentError, "expected array[#{x.size}], got #{v}"
    end
    x.zip(v) { |a, b| _load a, b }
  when Hash
    return x.each { |k, y| _load y, nil } if v.nil?
    unless Hash === v
      raise ArgumentError, "expected hash, got #{v}"
    end
    x.each { |k, y| _load y, v[k] }
  else
    raise ArgumentError, "expected hash, array, sym, int, got #{x}"
  end
ensure
  $@.shift if $@
end
_unpack(x) click to toggle source
# File lib/undll32.rb, line 126
def _unpack x
  case x
  when Integer
    buffer[(@_i += x) - x, x].sub(/\0+$/, '')
  when Symbol
    n = { C: 1, S: 2, L: 4, Q: 8 }[x]
    buffer[(@_i += n) - n, n].unpack1("#{x}")
  when Array
    x.map { |e| _unpack e }
  when Hash
    Hash[x.map { |k, v| [k, _unpack(v)] }]
  else
    raise ArgumentError, "expected hash, array, sym, int, got #{x}"
  end
ensure
  $@.shift if $@
end
buffer() click to toggle source
# File lib/undll32.rb, line 73
def buffer
  @buffer ||= _buffer(@struct)
end
load(v) click to toggle source
# File lib/undll32.rb, line 82
def load v
  @_i = 0
  _load @struct, v
  unpack
end
unpack() click to toggle source
# File lib/undll32.rb, line 77
def unpack
  @_i = 0
  _unpack @struct
end