misc/libphysfs/lzma/CPP/Common/MyVector.h
author nemo
Mon, 10 Apr 2017 12:06:43 -0400
changeset 12213 bb5522e88ab2
permissions -rw-r--r--
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash

// Common/Vector.h

#ifndef __COMMON_VECTOR_H
#define __COMMON_VECTOR_H

#include "Defs.h"

class CBaseRecordVector
{
  void MoveItems(int destIndex, int srcIndex);
protected:
  int _capacity;
  int _size;
  void *_items;
  size_t _itemSize;
  
  void ReserveOnePosition();
  void InsertOneItem(int index);
  void TestIndexAndCorrectNum(int index, int &num) const
    { if (index + num > _size) num = _size - index; } 
public:
  CBaseRecordVector(size_t itemSize):
      _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}
  virtual ~CBaseRecordVector();
  void Free();
  int Size() const { return _size; }
  bool IsEmpty() const { return (_size == 0); }
  void Reserve(int newCapacity);
  virtual void Delete(int index, int num = 1);
  void Clear();
  void DeleteFrom(int index);
  void DeleteBack();
};

template <class T>
class CRecordVector: public CBaseRecordVector
{
public:
  CRecordVector():CBaseRecordVector(sizeof(T)){};
  CRecordVector(const CRecordVector &v):
    CBaseRecordVector(sizeof(T)) { *this = v;}
  CRecordVector& operator=(const CRecordVector &v)
  {
    Clear();
    return (*this += v);
  }
  CRecordVector& operator+=(const CRecordVector &v)
  {
    int size = v.Size();
    Reserve(Size() + size);
    for(int i = 0; i < size; i++)
      Add(v[i]);
    return *this;
  }
  int Add(T item)
  {
    ReserveOnePosition();
    ((T *)_items)[_size] = item;
    return _size++;
  }
  void Insert(int index, T item)
  {
    InsertOneItem(index);
    ((T *)_items)[index] = item;
  }
  // T* GetPointer() const { return (T*)_items; }
  // operator const T *() const { return _items; };
  const T& operator[](int index) const { return ((T *)_items)[index]; }
  T& operator[](int index) { return ((T *)_items)[index]; }
  const T& Front() const { return operator[](0); }
  T& Front()   { return operator[](0); }
  const T& Back() const { return operator[](_size - 1); }
  T& Back()   { return operator[](_size - 1); }

  void Swap(int i, int j)
  {
    T temp = operator[](i);
    operator[](i) = operator[](j);
    operator[](j) = temp;
  }

  int FindInSorted(const T& item) const
  {
    int left = 0, right = Size(); 
    while (left != right)
    {
      int mid = (left + right) / 2;
      const T& midValue = (*this)[mid];
      if (item == midValue)
        return mid;
      if (item < midValue)
        right = mid;
      else
        left = mid + 1;
    }
    return -1;
  }

  int AddToUniqueSorted(const T& item)
  {
    int left = 0, right = Size(); 
    while (left != right)
    {
      int mid = (left + right) / 2;
      const T& midValue = (*this)[mid];
      if (item == midValue)
        return mid;
      if (item < midValue)
        right = mid;
      else
        left = mid + 1;
    }
    Insert(right, item);
    return right;
  }

  static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param)
  { 
    T temp = p[k];
    for (;;)
    {
      int s = (k << 1);
      if (s > size)
        break;
      if (s < size && compare(p + s + 1, p + s, param) > 0)
        s++;
      if (compare(&temp, p + s, param) >= 0)
        break;
      p[k] = p[s]; 
      k = s;
    } 
    p[k] = temp; 
  }

  void Sort(int (*compare)(const T*, const T*, void *), void *param)
  {
    int size = _size;
    if (size <= 1)
      return;
    T* p = (&Front()) - 1;
    {
      int i = size / 2;
      do
        SortRefDown(p, i, size, compare, param);
      while(--i != 0);
    }
    do
    {
      T temp = p[size];
      p[size--] = p[1];
      p[1] = temp;
      SortRefDown(p, 1, size, compare, param);
    }
    while (size > 1);
  }
};

typedef CRecordVector<int> CIntVector;
typedef CRecordVector<unsigned int> CUIntVector;
typedef CRecordVector<bool> CBoolVector;
typedef CRecordVector<unsigned char> CByteVector;
typedef CRecordVector<void *> CPointerVector;

template <class T>
class CObjectVector: public CPointerVector
{
public:
  CObjectVector(){};
  ~CObjectVector() { Clear(); }
  CObjectVector(const CObjectVector &objectVector)
    { *this = objectVector; }
  CObjectVector& operator=(const CObjectVector &objectVector)
  {
    Clear();
    return (*this += objectVector);
  }
  CObjectVector& operator+=(const CObjectVector &objectVector)
  {
    int size = objectVector.Size();
    Reserve(Size() + size);
    for(int i = 0; i < size; i++)
      Add(objectVector[i]);
    return *this;
  }
  const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }
  T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }
  T& Front() { return operator[](0); }
  const T& Front() const { return operator[](0); }
  T& Back() { return operator[](_size - 1); }
  const T& Back() const { return operator[](_size - 1); }
  int Add(const T& item)
    { return CPointerVector::Add(new T(item)); }
  void Insert(int index, const T& item)
    { CPointerVector::Insert(index, new T(item)); }
  virtual void Delete(int index, int num = 1)
  {
    TestIndexAndCorrectNum(index, num);
    for(int i = 0; i < num; i++)
      delete (T *)(((void **)_items)[index + i]);
    CPointerVector::Delete(index, num);
  }
  int Find(const T& item) const
  {
    for(int i = 0; i < Size(); i++)
      if (item == (*this)[i])
        return i;
      return -1;
  }
  int FindInSorted(const T& item) const
  {
    int left = 0, right = Size(); 
    while (left != right)
    {
      int mid = (left + right) / 2;
      const T& midValue = (*this)[mid];
      if (item == midValue)
        return mid;
      if (item < midValue)
        right = mid;
      else
        left = mid + 1;
    }
    return -1;
  }
  int AddToSorted(const T& item)
  {
    int left = 0, right = Size(); 
    while (left != right)
    {
      int mid = (left + right) / 2;
      const T& midValue = (*this)[mid];
      if (item == midValue)
      {
        right = mid + 1;
        break;
      }
      if (item < midValue)
        right = mid;
      else
        left = mid + 1;
    }
    Insert(right, item);
    return right;
  }

  void Sort(int (*compare)(void *const *, void *const *, void *), void *param) 
    { CPointerVector::Sort(compare, param); }

  static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)
    { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }
  void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }
};

#endif