module Fluent::Configurable::ClassMethods

def config_defaults

def config_defaults
  singleton_value(:_config_defaults)
end

def config_defaults_set

def config_defaults_set
  singleton_value_set(:_config_defaults)
end

def config_param(name, *args, &block)

def config_param(name, *args, &block)
  name = name.to_sym
  opts = {}
  args.each {|a|
    if a.is_a?(Symbol)
      opts[:type] = a
    elsif a.is_a?(Hash)
      opts.merge!(a)
    else
      raise ArgumentError, "wrong number of arguments (#{1+args.length} for #{block ? 2 : 3})"
    end
  }
  type = opts[:type]
  if block && type
    raise ArgumentError, "wrong number of arguments (#{1+args.length} for #{block ? 2 : 3})"
  end
  block ||= case type
      when :string, nil
        Proc.new {|val| val }
      when :integer
        Proc.new {|val| val.to_i }
      when :float
        Proc.new {|val| val.to_f }
      when :size
        Proc.new {|val| Config.size_value(val) }
      when :bool
        Proc.new {|val| Config.bool_value(val) }
      when :time
        Proc.new {|val| Config.time_value(val) }
      else
        raise ArgumentError, "unknown config_param type `#{type}'"
      end
  params = config_params_set
  params.delete(name)
  params[name] = [block, opts]
  if opts.has_key?(:default)
    config_set_default(name, opts[:default])
  end
  attr_accessor name
end

def config_params

def config_params
  singleton_value(:_config_params)
end

def config_params_set

def config_params_set
  singleton_value_set(:_config_params)
end

def config_set_default(name, defval)

def config_set_default(name, defval)
  name = name.to_sym
  defaults = config_defaults_set
  defaults.delete(name)
  defaults[name] = defval
  nil
end

def singleton_value(name)

def singleton_value(name)
  val = {}
  ancestors.reverse_each {|c|
    if c.methods(false).include?(name)
      val.merge!(c.__send__(name))
    end
  }
  val
end

def singleton_value_set(name)

def singleton_value_set(name)
  if methods(false).include?(name)
    __send__(name)
  else
    val = {}
    define_singleton_method(name) { val }
    val
  end
end