/* Copyright 2017 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

#include "./compound_dictionary.h"

#include "../common/platform.h"
#include <brotli/types.h>
#include "./memory.h"
#include "./quality.h"

static PreparedDictionary* CreatePreparedDictionaryWithParams(MemoryManager* m,
    const uint8_t* source, size_t source_size, uint32_t bucket_bits,
    uint32_t slot_bits, uint32_t hash_bits, uint16_t bucket_limit) {
  /* Step 1: create "bloated" hasher. */
  uint32_t num_slots = 1u << slot_bits;
  uint32_t num_buckets = 1u << bucket_bits;
  uint32_t hash_shift = 64u - bucket_bits;
  uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);
  uint32_t slot_mask = num_slots - 1;
  size_t alloc_size = (sizeof(uint32_t) << slot_bits) +
      (sizeof(uint32_t) << slot_bits) +
      (sizeof(uint16_t) << bucket_bits) +
      (sizeof(uint32_t) << bucket_bits) +
      (sizeof(uint32_t) * source_size);
  uint8_t* flat = NULL;
  PreparedDictionary* result = NULL;
  uint16_t* num = NULL;
  uint32_t* bucket_heads = NULL;
  uint32_t* next_bucket = NULL;
  uint32_t* slot_offsets = NULL;
  uint16_t* heads = NULL;
  uint32_t* items = NULL;
  uint8_t* source_copy = NULL;
  uint32_t i;
  uint32_t* slot_size = NULL;
  uint32_t* slot_limit = NULL;
  uint32_t total_items = 0;
  if (slot_bits > 16) return NULL;
  if (slot_bits > bucket_bits) return NULL;
  if (bucket_bits - slot_bits >= 16) return NULL;

  flat = BROTLI_ALLOC(m, uint8_t, alloc_size);
  if (BROTLI_IS_OOM(m)) return NULL;

  slot_size = (uint32_t*)flat;
  slot_limit = (uint32_t*)(&slot_size[num_slots]);
  num = (uint16_t*)(&slot_limit[num_slots]);
  bucket_heads = (uint32_t*)(&num[num_buckets]);
  next_bucket = (uint32_t*)(&bucket_heads[num_buckets]);
  memset(num, 0, num_buckets * sizeof(num[0]));

  /* TODO: apply custom "store" order. */
  for (i = 0; i + 7 < source_size; ++i) {
    const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&source[i]) & hash_mask) *
        kPreparedDictionaryHashMul64Long;
    const uint32_t key = (uint32_t)(h >> hash_shift);
    uint16_t count = num[key];
    next_bucket[i] = (count == 0) ? ((uint32_t)(-1)) : bucket_heads[key];
    bucket_heads[key] = i;
    count++;
    if (count > bucket_limit) count = bucket_limit;
    num[key] = count;
  }

  /* Step 2: find slot limits. */
  for (i = 0; i < num_slots; ++i) {
    BROTLI_BOOL overflow = BROTLI_FALSE;
    slot_limit[i] = bucket_limit;
    while (BROTLI_TRUE) {
      uint32_t limit = slot_limit[i];
      size_t j;
      uint32_t count = 0;
      overflow = BROTLI_FALSE;
      for (j = i; j < num_buckets; j += num_slots) {
        uint32_t size = num[j];
        /* Last chain may span behind 64K limit; overflow happens only if
           we are about to use 0xFFFF+ as item offset. */
        if (count >= 0xFFFF) {
          overflow = BROTLI_TRUE;
          break;
        }
        if (size > limit) size = limit;
        count += size;
      }
      if (!overflow) {
        slot_size[i] = count;
        total_items += count;
        break;
      }
      slot_limit[i]--;
    }
  }

  /* Step 3: transfer data to "slim" hasher. */
  alloc_size = sizeof(PreparedDictionary) + (sizeof(uint32_t) << slot_bits) +
      (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) * total_items) +
      source_size;

  result = (PreparedDictionary*)BROTLI_ALLOC(m, uint8_t, alloc_size);
  if (BROTLI_IS_OOM(m)) {
    BROTLI_FREE(m, flat);
    return NULL;
  }
  slot_offsets = (uint32_t*)(&result[1]);
  heads = (uint16_t*)(&slot_offsets[num_slots]);
  items = (uint32_t*)(&heads[num_buckets]);
  source_copy = (uint8_t*)(&items[total_items]);

  result->magic = kPreparedDictionaryMagic;
  result->source_offset = total_items;
  result->source_size = (uint32_t)source_size;
  result->hash_bits = hash_bits;
  result->bucket_bits = bucket_bits;
  result->slot_bits = slot_bits;

  total_items = 0;
  for (i = 0; i < num_slots; ++i) {
    slot_offsets[i] = total_items;
    total_items += slot_size[i];
    slot_size[i] = 0;
  }
  for (i = 0; i < num_buckets; ++i) {
    uint32_t slot = i & slot_mask;
    uint32_t count = num[i];
    uint32_t pos;
    size_t j;
    size_t cursor = slot_size[slot];
    if (count > slot_limit[slot]) count = slot_limit[slot];
    if (count == 0) {
      heads[i] = 0xFFFF;
      continue;
    }
    heads[i] = (uint16_t)cursor;
    cursor += slot_offsets[slot];
    slot_size[slot] += count;
    pos = bucket_heads[i];
    for (j = 0; j < count; j++) {
      items[cursor++] = pos;
      pos = next_bucket[pos];
    }
    items[cursor - 1] |= 0x80000000;
  }

  BROTLI_FREE(m, flat);
  memcpy(source_copy, source, source_size);
  return result;
}

PreparedDictionary* CreatePreparedDictionary(MemoryManager* m,
    const uint8_t* source, size_t source_size) {
  uint32_t bucket_bits = 17;
  uint32_t slot_bits = 7;
  uint32_t hash_bits = 40;
  uint16_t bucket_limit = 32;
  size_t volume = 16u << bucket_bits;
  /* Tune parameters to fit dictionary size. */
  while (volume < source_size && bucket_bits < 22) {
    bucket_bits++;
    slot_bits++;
    volume <<= 1;
  }
  return CreatePreparedDictionaryWithParams(m,
      source, source_size, bucket_bits, slot_bits, hash_bits, bucket_limit);
}

void DestroyPreparedDictionary(MemoryManager* m,
    PreparedDictionary* dictionary) {
  if (!dictionary) return;
  BROTLI_FREE(m, dictionary);
}

BROTLI_BOOL AttachPreparedDictionary(
    CompoundDictionary* compound, const PreparedDictionary* dictionary) {
  size_t length = 0;
  size_t index = 0;

  if (compound->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) {
    return BROTLI_FALSE;
  }

  if (!dictionary) return BROTLI_FALSE;

  length = dictionary->source_size;
  index = compound->num_chunks;
  compound->total_size += length;
  compound->chunks[index] = dictionary;
  compound->chunk_offsets[index + 1] = compound->total_size;
  {
    uint32_t* slot_offsets = (uint32_t*)(&dictionary[1]);
    uint16_t* heads = (uint16_t*)(&slot_offsets[1u << dictionary->slot_bits]);
    uint32_t* items = (uint32_t*)(&heads[1u << dictionary->bucket_bits]);
    compound->chunk_source[index] =
        (const uint8_t*)(&items[dictionary->source_offset]);
  }
  compound->num_chunks++;
  return BROTLI_TRUE;
}
