/*
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Author(s): Behdad Esfahbod
 */

#ifndef HB_BIT_VECTOR_HH
#define HB_BIT_VECTOR_HH

#include "hb.hh"

struct hb_min_max_t
{
  void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
  void add_range (hb_codepoint_t a, hb_codepoint_t b)
  {
    min_v = hb_min (min_v, a);
    max_v = hb_max (max_v, b);
  }

  template <typename set_t>
  void union_ (const set_t &set)
  {
    hb_codepoint_t set_min = set.get_min ();
    if (unlikely (set_min == HB_CODEPOINT_INVALID))
      return;
    hb_codepoint_t set_max = set.get_max ();
    min_v = hb_min (min_v, set_min);
    max_v = hb_max (max_v, set_max);
  }

  hb_codepoint_t get_min () const { return min_v; }
  hb_codepoint_t get_max () const { return max_v; }

  private:
  hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
  hb_codepoint_t max_v = 0;
};

struct hb_bit_vector_t
{
  hb_bit_vector_t () = default;
  hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
  hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;

  // Move
  hb_bit_vector_t (hb_bit_vector_t &&other)
		: min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
  {
    other.min_v = other.max_v = other.count = 0;
    other.elts = nullptr;
  }
  hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
  {
    hb_swap (min_v, other.min_v);
    hb_swap (max_v, other.max_v);
    hb_swap (count, other.count);
    hb_swap (elts, other.elts);
    return *this;
  }

  hb_bit_vector_t (unsigned min_v, unsigned max_v)
    : min_v (min_v), max_v (max_v)
  {
    if (unlikely (min_v > max_v))
    {
      min_v = max_v = count = 0;
      return;
    }

    unsigned num = (max_v - min_v + sizeof (elt_t) * 8) / (sizeof (elt_t) * 8);
    elts = (elt_t *) hb_calloc (num, sizeof (elt_t));
    if (unlikely (!elts))
    {
      min_v = max_v = count = 0;
      return;
    }

    count = max_v - min_v + 1;
  }
  ~hb_bit_vector_t ()
  {
    hb_free (elts);
  }

  void add (hb_codepoint_t g) { elt (g) |= mask (g); }
  void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
  void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
  bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
  bool may_have (hb_codepoint_t g) const { return get (g); }

  bool operator [] (hb_codepoint_t g) const { return get (g); }
  bool operator () (hb_codepoint_t g) const { return get (g); }

  void add_range (hb_codepoint_t a, hb_codepoint_t b)
  {
    if (unlikely (!count || a > b || a < min_v || b > max_v))
      return;

    elt_t *la = &elt (a);
    elt_t *lb = &elt (b);
    if (la == lb)
      *la |= (mask (b) << 1) - mask(a);
    else
    {
      *la |= ~(mask (a) - 1llu);
      la++;

      hb_memset (la, 0xff, (char *) lb - (char *) la);

      *lb |= ((mask (b) << 1) - 1llu);
    }
  }
  void del_range (hb_codepoint_t a, hb_codepoint_t b)
  {
    if (unlikely (!count || a > b || a < min_v || b > max_v))
      return;

    elt_t *la = &elt (a);
    elt_t *lb = &elt (b);
    if (la == lb)
      *la &= ~((mask (b) << 1llu) - mask(a));
    else
    {
      *la &= mask (a) - 1;
      la++;

      hb_memset (la, 0, (char *) lb - (char *) la);

      *lb &= ~((mask (b) << 1) - 1llu);
    }
  }
  void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
  { if (v) add_range (a, b); else del_range (a, b); }

  template <typename set_t>
  void union_ (const set_t &set)
  {
    for (hb_codepoint_t g : set)
      add (g);
  }

  typedef unsigned long long elt_t;
  static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
  static constexpr unsigned ELT_MASK = ELT_BITS - 1;

  static constexpr elt_t zero = 0;

  elt_t &elt (hb_codepoint_t g)
  {
    g -= min_v;
    if (unlikely (g >= count))
      return Crap(elt_t);
    return elts[g / ELT_BITS];
  }
  const elt_t& elt (hb_codepoint_t g) const
  {
    g -= min_v;
    if (unlikely (g >= count))
      return Null(elt_t);
    return elts[g / ELT_BITS];
  }

  static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }

  hb_codepoint_t min_v = 0, max_v = 0, count = 0;
  elt_t *elts = nullptr;
};


#endif /* HB_BIT_VECTOR_HH */
