class TTFunk::EncodedString

Encoded string takes care of placeholders in binary strings. Placeholders are used when bytes need to be placed in the stream before their value is known.

@api private

Public Class Methods

new() { |self| ... } click to toggle source

@yieldparam [self]

# File lib/ttfunk/encoded_string.rb, line 24
def initialize
  yield(self) if block_given?
end

Public Instance Methods

<<(obj) click to toggle source

Append to string.

@param obj [String, Placeholder, EncodedString] @return [self]

# File lib/ttfunk/encoded_string.rb, line 32
def <<(obj)
  case obj
  when String
    io << obj
  when Placeholder
    add_placeholder(obj)
    io << ("\0" * obj.length)
  when self.class
    # adjust placeholders to be relative to the entire encoded string
    obj.placeholders.each_pair do |_, placeholder|
      add_placeholder(placeholder.dup, placeholder.position + io.length)
    end

    io << obj.unresolved_string
  end

  self
end
align!(width = 4) click to toggle source

Append padding to align string to the specified word width.

@param width [Integer] @return [self]

# File lib/ttfunk/encoded_string.rb, line 66
def align!(width = 4)
  if (length % width).positive?
    self << ("\0" * (width - (length % width)))
  end

  self
end
bytes() click to toggle source

Raw bytes.

@return [Array<Integer>] @raise [UnresolvedPlaceholderError] if there are any unresolved

placeholders left.
# File lib/ttfunk/encoded_string.rb, line 100
def bytes
  string.bytes
end
concat(*objs) click to toggle source

Append multiple objects.

@param objs [Array<String, Placeholder, EncodedString>] @return [self]

# File lib/ttfunk/encoded_string.rb, line 55
def concat(*objs)
  objs.each do |obj|
    self << obj
  end
  self
end
length() click to toggle source

Length of this string.

@return [Integer]

# File lib/ttfunk/encoded_string.rb, line 77
def length
  io.length
end
placeholders() click to toggle source

Plaholders

@return [Hash{Symbol => Plaholder}]

# File lib/ttfunk/encoded_string.rb, line 131
def placeholders
  @placeholders ||= {}
end
resolve_placeholder(name, value) click to toggle source

Resolve placeholder.

@param name [Symbol] @param value [String] @return [void]

# File lib/ttfunk/encoded_string.rb, line 116
def resolve_placeholder(name, value)
  last_pos = io.pos

  if (placeholder = placeholders[name])
    io.seek(placeholder.position)
    io.write(value[0..placeholder.length])
    placeholders.delete(name)
  end
ensure
  io.seek(last_pos)
end
string() click to toggle source

Raw string.

@return [String] @raise [UnresolvedPlaceholderError] if there are any unresolved

placeholders left.
# File lib/ttfunk/encoded_string.rb, line 86
def string
  unless placeholders.empty?
    raise UnresolvedPlaceholderError,
      "string contains #{placeholders.size} unresolved placeholder(s)"
  end

  io.string
end
unresolved_string() click to toggle source

Unresolved raw string.

@return [String]

# File lib/ttfunk/encoded_string.rb, line 107
def unresolved_string
  io.string
end

Private Instance Methods

add_placeholder(new_placeholder, pos = io.pos) click to toggle source
# File lib/ttfunk/encoded_string.rb, line 137
def add_placeholder(new_placeholder, pos = io.pos)
  if placeholders.include?(new_placeholder.name)
    raise DuplicatePlaceholderError,
      "placeholder #{new_placeholder.name} already exists"
  end

  new_placeholder.position = pos
  placeholders[new_placeholder.name] = new_placeholder
end
io() click to toggle source
# File lib/ttfunk/encoded_string.rb, line 147
def io
  @io ||= StringIO.new(''.b).binmode
end