class SQLite3::Driver::FFI::Driver

def self.api_delegate(name)

def self.api_delegate(name)
  define_method(name) { |*args| API.send("sqlite3_#{name}", *args) }
end

def aggregate_context(context)

def aggregate_context(context)
  ptr = API.sqlite3_aggregate_context(context, 4)
  ptr.free = nil
  obj = (ptr ? ptr.to_object : nil)
  if obj.nil?
    obj = Hash.new
    ptr.set_object obj
  end
  obj
end

def bind_blob(stmt, index, value)

def bind_blob(stmt, index, value)
  s = value.to_s
  API.sqlite3_bind_blob(stmt, index, s, s.length, TRANSIENT)
end

def bind_text(stmt, index, value, utf16 = false)

def bind_text(stmt, index, value, utf16 = false)
  s = value.to_s
  method = (utf16 ? :sqlite3_bind_text16 : :sqlite3_bind_text)
  API.send(method, stmt, index, s, s.length, TRANSIENT)
end

def busy_handler(db, data = nil, &block)

def busy_handler(db, data = nil, &block)
  @busy_handler = block
  unless @busy_handler_callback
    @busy_handler_callback = ::DL.callback("IPI") do |cookie, timeout|
      @busy_handler.call(cookie, timeout) || 0
    end
  end
  API.sqlite3_busy_handler(db, block&&@busy_handler_callback, data)
end

def column_blob(stmt, column)

def column_blob(stmt, column)
  blob = API.sqlite3_column_blob(stmt, column)
  blob.free = nil
  blob.to_s(API.sqlite3_column_bytes(stmt, column))
end

def column_decltype(stmt, column)

def column_decltype(stmt, column)
  result = API.sqlite3_column_decltype(stmt, column)
  result ? result.to_s : nil
end

def column_name(stmt, column)

def column_name(stmt, column)
  result = API.sqlite3_column_name(stmt, column)
  result ? result.to_s : nil
end

def column_text(stmt, column)

def column_text(stmt, column)
  result = API.sqlite3_column_text(stmt, column)
  result ? result.to_s : nil
end

def complete?(sql, utf16 = false)

def complete?(sql, utf16 = false)
  API.send(utf16 ? :sqlite3_complete16 : :sqlite3_complete, sql)
end

def create_function(db, name, args, text, cookie, func, step, final)

def create_function(db, name, args, text, cookie, func, step, final)
  # begin
  if @func_handler_callback.nil? && func
    @func_handler_callback = ::DL.callback("0PIP") do |context,nargs,args|
      args = args.to_s(nargs*4).unpack("L*").map {|i| ::FFI::MemoryPointer.new(i)}
      data = API.sqlite3_user_data(context).to_object
      data[:func].call(context, *args)
    end
  end
  if @step_handler_callback.nil? && step
    @step_handler_callback = ::DL.callback("0PIP") do |context,nargs,args|
      args = args.to_s(nargs*4).unpack("L*").map {|i| ::FFI::MemoryPointer.new(i)}
      data = API.sqlite3_user_data(context).to_object
      data[:step].call(context, *args)
    end
  end
  if @final_handler_callback.nil? && final
    @final_handler_callback = ::DL.callback("0P") do |context|
      data = API.sqlite3_user_data(context).to_object
      data[:final].call(context)
    end
  end
  data = {
    :cookie => cookie,
    :name => name,
    :func => func,
    :step => step,
    :final => final
  }
  API.sqlite3_create_function(db, name, args, text, data, (func ? @func_handler_callback : nil), (step ? @step_handler_callback : nil), (final ? @final_handler_callback : nil))
end

def errmsg(db, utf16 = false)

def errmsg(db, utf16 = false)
  if utf16
    msg = API.sqlite3_errmsg16(db)
    msg.free = nil
    msg.to_s(utf16_length(msg))
  else
    API.sqlite3_errmsg(db)
  end
end

def open(filename, utf16 = false)

def open(filename, utf16 = false)
  handle = ::FFI::MemoryPointer.new(:pointer)
  result = API.send((utf16 ? :sqlite3_open16 : :sqlite3_open), filename, handle)
  [result, handle.get_pointer(0)]
end

def prepare(db, sql, utf16 = false)

def prepare(db, sql, utf16 = false)
  handle = ::FFI::MemoryPointer.new(:pointer)
  remainder = ::FFI::MemoryPointer.new(:pointer)
  result = API.send((utf16 ? :sqlite3_prepare16 : :sqlite3_prepare), db, sql, sql.length, handle, remainder)
  # TODO: UTF-16
  # args = utf16 ? [utf16_length(remainder)] : []
  # remainder = remainder.to_s(*args)
  [result, handle.get_pointer(0), remainder.get_pointer(0).get_string(0)]
end

def result_text(func, text, utf16 = false)

def result_text(func, text, utf16 = false)
  method = case utf16
           when false, nil
             :sqlite3_result_text
           when :le
             :sqlite3_result_text16le
           when :be
             :sqlite3_result_text16be
           else
             :sqlite3_result_text16
           end
  s = text.to_s
  API.send(method, func, s, s.length, TRANSIENT)
end

def set_authorizer(db, data = nil, &block)

def set_authorizer(db, data = nil, &block)
  @authorizer_handler = block
  unless @authorizer_handler_callback
    @authorizer_handler_callback = ::DL.callback("IPIPPPP") do |cookie,mode,a,b,c,d|
      @authorizer_handler.call(cookie, mode, a&&a.to_s, b&&b.to_s, c&&c.to_s, d&&d.to_s) || 0
    end
  end
  API.sqlite3_set_authorizer(db, block&&@authorizer_handler_callback, data)
end

def trace(db, data = nil, &block)

def trace(db, data = nil, &block)
  @trace_handler = block
  unless @trace_handler_callback
    @trace_handler_callback = ::DL.callback("IPS") do |cookie,sql|
      @trace_handler.call(cookie ? cookie.to_object : nil, sql) || 0
    end
  end
  API.sqlite3_trace(db, block&&@trace_handler_callback, data)
end

def utf16_length(ptr)

def utf16_length(ptr)
  len = 0
  loop do
    break if ptr[len,1] == "\0"
    len += 2
  end
  len
end

def value_blob(value)

def value_blob(value)
  blob = API.sqlite3_value_blob(value)
  blob.free = nil
  blob.to_s(API.sqlite3_value_bytes(value))
end

def value_text(value, utf16 = false)

def value_text(value, utf16 = false)
  method = case utf16
           when nil, false
             :sqlite3_value_text
           when :le
             :sqlite3_value_text16le
           when :be
             :sqlite3_value_text16be
           else
             :sqlite3_value_text16
           end
  result = API.send(method, value)
  if utf16
    result.free = nil
    size = API.sqlite3_value_bytes(value)
    result = result.to_s(size)
  end
  result
end