class CFPropertyList::Binary

def unique_and_count_values(value)

will only be saved once and referenced later
„unique” and count values. „Unique” means, several objects (e.g. strings)
def unique_and_count_values(value)
  # no uniquing for other types than CFString and CFData
  if(value.is_a?(CFInteger) || value.is_a?(CFReal)) then
    val = value.value
    if(value.is_a?(CFInteger)) then
      @int_size += Binary.bytes_int(val)
    else
      @misc_size += 9 # 9 bytes (8 + marker byte) for real
    end
    @count_objects += 1
    return
  elsif(value.is_a?(CFDate)) then
    @misc_size += 9
    @count_objects += 1
    return
  elsif(value.is_a?(CFBoolean)) then
    @count_objects += 1
    @misc_size += 1
    return
  elsif(value.is_a?(CFArray)) then
    cnt = 0
    value.value.each do |v|
      cnt += 1
      unique_and_count_values(v)
      @object_refs += 1 # each array member is a ref
    end
    @count_objects += 1
    @int_size += Binary.bytes_size_int(cnt)
    @misc_size += 1 # marker byte for array
    return
  elsif(value.is_a?(CFDictionary)) then
    cnt = 0
    value.value.each_pair do |k,v|
      cnt += 1
      if(!@unique_table.has_key?(k))
        @unique_table[k] = 0
        @string_size += Binary.binary_strlen(k) + 1
        @int_size += Binary.bytes_size_int(Binary.charset_strlen(k,'UTF-8'))
      end
      @object_refs += 2 # both, key and value, are refs
      @unique_table[k] += 1
      unique_and_count_values(v)
    end
    @count_objects += 1
    @misc_size += 1 # marker byte for dict
    @int_size += Binary.bytes_size_int(cnt)
    return
  elsif(value.is_a?(CFData)) then
    val = value.decoded_value
    @int_size += Binary.bytes_size_int(val.length)
    @misc_size += val.length
    @count_objects += 1
    return
  end
  val = value.value
  if(!@unique_table.has_key?(val)) then
    @unique_table[val] = 0
    @string_size += Binary.binary_strlen(val) + 1
    @int_size += Binary.bytes_size_int(Binary.charset_strlen(val,'UTF-8'))
  end
  @unique_table[val] += 1
end