class ICU::Transliteration::Transliterator

Public Class Methods

new(id, rules = nil, direction = :forward) click to toggle source
# File lib/ffi-icu/transliteration.rb, line 25
def initialize(id, rules = nil, direction = :forward)
  rules_length = 0

  if rules
    rules_length = rules.jlength + 1
    rules = UCharPointer.from_string(rules)
  end

  parse_error = Lib::UParseError.new
  begin
    Lib.check_error do |status|
      ptr = Lib.utrans_openU(UCharPointer.from_string(id), id.jlength, direction, rules, rules_length, @parse_error, status)
      @tr = FFI::AutoPointer.new(ptr, Lib.method(:utrans_close))
    end
  rescue ICU::Error => ex
    raise ex, "#{ex.message} (#{parse_error})"
  end
end

Public Instance Methods

transliterate(from) click to toggle source
# File lib/ffi-icu/transliteration.rb, line 44
def transliterate(from)
  # this is a bit unpleasant

  unicode_size = from.unpack("U*").size
  capacity     = unicode_size + 1
  buf          = UCharPointer.from_string(from, capacity)
  limit        = FFI::MemoryPointer.new :int32
  text_length  = FFI::MemoryPointer.new :int32

  retried = false

  begin
    # resets to original size on retry
    [limit, text_length].each do |ptr|
      ptr.put_int32(0, unicode_size)
    end

    Lib.check_error do |error|
      Lib.utrans_transUChars(@tr, buf, text_length, capacity, 0, limit, error)
    end
  rescue BufferOverflowError
    new_size = text_length.get_int32(0)
    $stderr.puts "BufferOverflowError, needs: #{new_size}" if $DEBUG

    raise BufferOverflowError, "needed #{new_size}" if retried

    capacity = new_size + 1

    # create a new buffer with more capacity instead of resizing,
    # since the old buffer now has result data
    buf.free
    buf = UCharPointer.from_string(from, capacity)

    retried = true
    retry
  end

  buf.string text_length.get_int32(0)
end