# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import os
import struct
import sys

def Main(args):
  if len(args) < 4:
    print(
        "Usage: %s output.hmap Foo.framework header1.h..." % args[0],
        file=sys.stderr)
    return 1

  (out, framework, all_headers) = args[1], args[2], args[3:]

  framework_name = os.path.basename(framework).split('.')[0]
  all_headers = map(os.path.abspath, all_headers)
  filelist = {}
  for header in all_headers:
    filename = os.path.basename(header)
    filelist[filename] = header
    filelist[os.path.join(framework_name, filename)] = header
  WriteHmap(out, filelist)
  return 0


def NextGreaterPowerOf2(x):
  return 2**(x).bit_length()


def WriteHmap(output_name, filelist):
  """Generates a header map based on |filelist|.

  Per Mark Mentovai:
    A header map is structured essentially as a hash table, keyed by names used
    in #includes, and providing pathnames to the actual files.

  The implementation below and the comment above comes from inspecting:
    http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt
  while also looking at the implementation in clang in:
    https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp
  """
  magic = 1751998832
  version = 1
  _reserved = 0
  count = len(filelist)
  capacity = NextGreaterPowerOf2(count)
  strings_offset = 24 + (12 * capacity)
  max_value_length = len(max(filelist.values(), key=lambda v: len(v)))

  out = open(output_name, 'wb')
  out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset,
                        count, capacity, max_value_length))

  # Create empty hashmap buckets.
  buckets = [None] * capacity
  for file, path in filelist.items():
    key = 0
    for c in file:
      key += ord(c.lower()) * 13

    # Fill next empty bucket.
    while buckets[key & capacity - 1] is not None:
      key = key + 1
    buckets[key & capacity - 1] = (file, path)

  next_offset = 1
  for bucket in buckets:
    if bucket is None:
      out.write(struct.pack('<LLL', 0, 0, 0))
    else:
      (file, path) = bucket
      key_offset = next_offset
      prefix_offset = key_offset + len(file) + 1
      suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1
      next_offset = suffix_offset + len(os.path.basename(path)) + 1
      out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset))

  # Pad byte since next offset starts at 1.
  out.write(struct.pack('<x'))

  for bucket in buckets:
    if bucket is not None:
      (file, path) = bucket
      base = os.path.dirname(path) + os.sep
      path = os.path.basename(path)
      file = file.encode('UTF-8')
      base = base.encode('UTF-8')
      path = path.encode('UTF-8')
      out.write(struct.pack('<%ds' % len(file), file))
      out.write(struct.pack('<s', b'\0'))
      out.write(struct.pack('<%ds' % len(base), base))
      out.write(struct.pack('<s', b'\0'))
      out.write(struct.pack('<%ds' % len(path), path))
      out.write(struct.pack('<s', b'\0'))


if __name__ == '__main__':
  sys.exit(Main(sys.argv))
