/*
 * Copyright © 2017,2018  Google, Inc.
 *
 *  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.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_VECTOR_HH
#define HB_VECTOR_HH

#include "hb.hh"
#include "hb-array.hh"
#include "hb-null.hh"


template <typename Type>
struct hb_vector_t
{
  typedef Type item_t;
  enum { item_size = hb_static_size (Type) };

  HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
  hb_vector_t ()  { init (); }
  ~hb_vector_t () { fini (); }

  unsigned int length;
  private:
  int allocated; /* == -1 means allocation failed. */
  Type *arrayZ_;
  public:

  void init ()
  {
    allocated = length = 0;
    arrayZ_ = nullptr;
  }

  void fini ()
  {
    if (arrayZ_)
      free (arrayZ_);
    init ();
  }
  void fini_deep ()
  {
    Type *array = arrayZ();
    unsigned int count = length;
    for (unsigned int i = 0; i < count; i++)
      array[i].fini ();
    fini ();
  }

  const Type * arrayZ () const { return arrayZ_; }
        Type * arrayZ ()       { return arrayZ_; }

  Type& operator [] (int i_)
  {
    unsigned int i = (unsigned int) i_;
    if (unlikely (i >= length))
      return Crap (Type);
    return arrayZ()[i];
  }
  const Type& operator [] (int i_) const
  {
    unsigned int i = (unsigned int) i_;
    if (unlikely (i >= length))
      return Null(Type);
    return arrayZ()[i];
  }

  explicit_operator bool () const { return length; }

  hb_array_t<Type> as_array ()
  { return hb_array (arrayZ(), length); }
  hb_array_t<const Type> as_array () const
  { return hb_array (arrayZ(), length); }

  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
  { return as_array ().sub_array (start_offset, count);}
  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
  { return as_array ().sub_array (start_offset, count);}
  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
  { return as_array ().sub_array (start_offset, count);}
  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
  { return as_array ().sub_array (start_offset, count);}

  hb_sorted_array_t<Type> as_sorted_array ()
  { return hb_sorted_array (arrayZ(), length); }
  hb_sorted_array_t<const Type> as_sorted_array () const
  { return hb_sorted_array (arrayZ(), length); }

  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
  { return as_sorted_array ().sorted_sub_array (start_offset, count);}

  template <typename T> explicit_operator T * () { return arrayZ(); }
  template <typename T> explicit_operator const T * () const { return arrayZ(); }
  operator hb_array_t<Type> ()             { return as_array (); }
  operator hb_array_t<const Type> () const { return as_array (); }

  Type * operator  + (unsigned int i) { return arrayZ() + i; }
  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }

  Type *push ()
  {
    if (unlikely (!resize (length + 1)))
      return &Crap(Type);
    return &arrayZ()[length - 1];
  }
  Type *push (const Type& v)
  {
    Type *p = push ();
    *p = v;
    return p;
  }

  bool in_error () const { return allocated < 0; }

  /* Allocate for size but don't adjust length. */
  bool alloc (unsigned int size)
  {
    if (unlikely (allocated < 0))
      return false;

    if (likely (size <= (unsigned) allocated))
      return true;

    /* Reallocate */

    unsigned int new_allocated = allocated;
    while (size >= new_allocated)
      new_allocated += (new_allocated >> 1) + 8;

    Type *new_array = nullptr;
    bool overflows =
      (int) new_allocated < 0 ||
      (new_allocated < (unsigned) allocated) ||
      hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
    if (likely (!overflows))
      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));

    if (unlikely (!new_array))
    {
      allocated = -1;
      return false;
    }

    arrayZ_ = new_array;
    allocated = new_allocated;

    return true;
  }

  bool resize (int size_)
  {
    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
    if (!alloc (size))
      return false;

    if (size > length)
      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));

    length = size;
    return true;
  }

  void pop ()
  {
    if (!length) return;
    length--;
  }

  void remove (unsigned int i)
  {
    if (unlikely (i >= length))
      return;
    Type *array = arrayZ();
    memmove (static_cast<void *> (&array[i]),
	     static_cast<void *> (&array[i + 1]),
	     (length - i - 1) * sizeof (Type));
    length--;
  }

  void shrink (int size_)
  {
    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
     if (size < length)
       length = size;
  }

  template <typename T>
  Type *find (T v)
  {
    Type *array = arrayZ();
    for (unsigned int i = 0; i < length; i++)
      if (array[i] == v)
	return &array[i];
    return nullptr;
  }
  template <typename T>
  const Type *find (T v) const
  {
    const Type *array = arrayZ();
    for (unsigned int i = 0; i < length; i++)
      if (array[i] == v)
	return &array[i];
    return nullptr;
  }

  void qsort (int (*cmp)(const void*, const void*))
  { as_array ().qsort (cmp); }
  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
  { as_array ().qsort (start, end); }

  template <typename T>
  Type *lsearch (const T &x, Type *not_found = nullptr)
  { return as_array ().lsearch (x, not_found); }
  template <typename T>
  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
  { return as_array ().lsearch (x, not_found); }

  template <typename T>
  Type *bsearch (const T &x, Type *not_found = nullptr)
  { return as_sorted_array ().bsearch (x, not_found); }
  template <typename T>
  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
  { return as_sorted_array ().bsearch (x, not_found); }
  template <typename T>
  bool bfind (const T &x, unsigned int *i = nullptr,
		     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
		     unsigned int to_store = (unsigned int) -1) const
  { return as_sorted_array ().bfind (x, i, not_found, to_store); }
};


#endif /* HB_VECTOR_HH */
