module CFPropertyList

def guess(object, options = {})

cftypes = CFPropertyList.guess(x,:convert_unknown_to_string => true,:converter_method => :to_hash, :converter_with_opts => true)

+converter_method+:: Convert unknown objects to known objects calling +method_name+
+convert_unknown_to_string+:: Convert unknown objects to string calling to_str()
pass optional options hash. Only possible value actually:

cftypes = CFPropertyList.guess(x)
}
'a' => ['b','c','d']
x = {

Create CFType hierarchy by guessing the correct CFType, e.g.
def guess(object, options = {})
  case object
  when Fixnum, Integer       then CFInteger.new(object)
  when UidFixnum             then CFUid.new(object)
  when Float                 then CFReal.new(object)
  when TrueClass, FalseClass then CFBoolean.new(object)
  when Blob
    CFData.new(object, CFData::DATA_RAW)
  when String
    CFString.new(object)
  when Time, DateTime, Date  then CFDate.new(object)
  when Array, Enumerator, Enumerable::Enumerator
    ary = Array.new
    object.each do |o|
      ary.push CFPropertyList.guess(o, options)
    end
    CFArray.new(ary)
  when Hash
    hsh = Hash.new
    object.each_pair do |k,v|
      k = k.to_s if k.is_a?(Symbol)
      hsh[k] = CFPropertyList.guess(v, options)
    end
    CFDictionary.new(hsh)
  else
    case
    when Object.const_defined?('BigDecimal') && object.is_a?(BigDecimal)
      CFReal.new(object)
    when object.respond_to?(:read)
      raw_data = object.read
      # treat the data as a bytestring (ASCII-8BIT) if Ruby supports it.  Do this by forcing
      # the encoding, on the assumption that the bytes were read correctly, and just tagged with
      # an inappropriate encoding, rather than transcoding.
      raw_data.force_encoding(Encoding::ASCII_8BIT) if raw_data.respond_to?(:force_encoding)
      CFData.new(raw_data, CFData::DATA_RAW)
    when options[:converter_method] && object.respond_to?(options[:converter_method])
      if options[:converter_with_opts]
        CFPropertyList.guess(object.send(options[:converter_method],options),options)
      else
        CFPropertyList.guess(object.send(options[:converter_method]),options)
      end
    when options[:convert_unknown_to_string]
      CFString.new(object.to_s)
    else
      raise CFTypeError.new("Unknown class #{object.class.to_s}. Try using :convert_unknown_to_string if you want to use unknown object types!")
    end
  end
end

def native_types(object,keys_as_symbols=false)

Converts a CFType hiercharchy to native Ruby types
def native_types(object,keys_as_symbols=false)
  return if object.nil?
  if(object.is_a?(CFDate) || object.is_a?(CFString) || object.is_a?(CFInteger) || object.is_a?(CFReal) || object.is_a?(CFBoolean)) || object.is_a?(CFUid) then
    return object.value
  elsif(object.is_a?(CFData)) then
    return CFPropertyList::Blob.new(object.decoded_value)
  elsif(object.is_a?(CFArray)) then
    ary = []
    object.value.each do
      |v|
      ary.push CFPropertyList.native_types(v)
    end
    return ary
  elsif(object.is_a?(CFDictionary)) then
    hsh = {}
    object.value.each_pair do
      |k,v|
      k = k.to_sym if keys_as_symbols
      hsh[k] = CFPropertyList.native_types(v)
    end
    return hsh
  end
end