/*
 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */
#include <cstring>

#include "utilities/align.hpp"
#include "utilities/count_leading_zeros.hpp"
#include "utilities/packedTable.hpp"

// The thresholds are inclusive, and in practice the limits are rounded
// to the nearest power-of-two - 1.
// Based on the max_key and max_value we figure out the number of bits required to store
// key and value; imagine that only as bits (not aligned to byte boundary... yet).
// Then we concatenate the bits for key and value, and 'add' 1-7 padding zeroes
// (high-order bits) to align on bytes.
// In the end we have each element in the table consuming 1-8 bytes (case with 0 bits for key
// is ruled out).
PackedTableBase::PackedTableBase(uint32_t max_key, uint32_t max_value) {
  unsigned int key_bits = max_key == 0 ? 0 : 32 - count_leading_zeros(max_key);
  unsigned int value_bits = max_value == 0 ? 0 : 32 - count_leading_zeros(max_value);
  _element_bytes = align_up(key_bits + value_bits, 8) / 8;
  // shifting left by 32 is undefined behaviour, and in practice returns 1
  _key_mask = key_bits >= 32 ? -1 : (1U << key_bits) - 1;
  _value_shift = key_bits;
  _value_mask = value_bits >= 32 ? -1 : (1U << value_bits) - 1;
  guarantee(_element_bytes > 0, "wouldn't work");
  assert(_element_bytes <= sizeof(uint64_t), "shouldn't happen");
}

// Note: we require the supplier to provide the elements in the final order as we can't easily sort
// within this method - qsort() accepts only pure function as comparator.
void PackedTableBuilder::fill(u1* table, size_t table_length, Supplier &supplier) const {
  uint32_t key, value;
  size_t offset = 0;
  for (; offset <= table_length && supplier.next(&key, &value); offset += _element_bytes) {
    assert((key & ~_key_mask) == 0, "key out of bounds");
    assert((value & ~_value_mask) == 0, "value out of bounds: %x vs. %x (%x)", value, _value_mask, ~_value_mask);
    uint64_t element = static_cast<uint64_t>(key) | (static_cast<uint64_t>(value) << _value_shift);
    for (unsigned int i = 0; i < _element_bytes; ++i) {
      table[offset + i] = static_cast<u1>(0xFF & element);
      element >>= 8;
    }
  }

  assert(offset == table_length, "Did not fill whole array");
  assert(!supplier.next(&key, &value), "Supplier has more elements");
}

uint64_t PackedTableLookup::read_element(size_t offset) const {
  uint64_t element = 0;
  for (unsigned int i = 0; i < _element_bytes; ++i) {
    element |= static_cast<uint64_t>(_table[offset + i]) << (8 * i);
  }
  assert((element & ~((uint64_t) _key_mask | ((uint64_t) _value_mask << _value_shift))) == 0, "read too much");
  return element;
}

bool PackedTableLookup::search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const {
  unsigned int low = 0, high = checked_cast<unsigned int>(_table_length / _element_bytes);
  assert(low < high, "must be");
  while (low < high) {
    unsigned int mid = low + (high - low) / 2;
    assert(mid >= low && mid < high, "integer overflow?");
    uint64_t element = read_element(_element_bytes * mid);
    // Ignoring high 32 bits in element on purpose
    uint32_t key = static_cast<uint32_t>(element) & _key_mask;
    int cmp = comparator.compare_to(key);
    if (cmp == 0) {
      *found_key = key;
      // Since __builtin_memcpy in read_element does not copy bits outside the element
      // anything above _value_mask << _value_shift should be zero.
      *found_value = checked_cast<uint32_t>(element >> _value_shift) & _value_mask;
      return true;
    } else if (cmp < 0) {
      high = mid;
    } else {
      low = mid + 1;
    }
  }
  return false;
}

#ifdef ASSERT
void PackedTableLookup::validate_order(Comparator &comparator) const {
  auto validator = [&] (size_t offset, uint32_t key, uint32_t value) {
    if (offset != 0) {
      assert(comparator.compare_to(key) < 0, "not sorted");
    }
    comparator.reset(key);
  };
  iterate(validator);
}
#endif
