Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Common/Vector.h |
michael@0 | 2 | |
michael@0 | 3 | #ifndef __COMMON_VECTOR_H |
michael@0 | 4 | #define __COMMON_VECTOR_H |
michael@0 | 5 | |
michael@0 | 6 | #include "Defs.h" |
michael@0 | 7 | |
michael@0 | 8 | class CBaseRecordVector |
michael@0 | 9 | { |
michael@0 | 10 | void MoveItems(int destIndex, int srcIndex); |
michael@0 | 11 | protected: |
michael@0 | 12 | int _capacity; |
michael@0 | 13 | int _size; |
michael@0 | 14 | void *_items; |
michael@0 | 15 | size_t _itemSize; |
michael@0 | 16 | |
michael@0 | 17 | void ReserveOnePosition(); |
michael@0 | 18 | void InsertOneItem(int index); |
michael@0 | 19 | void TestIndexAndCorrectNum(int index, int &num) const |
michael@0 | 20 | { if (index + num > _size) num = _size - index; } |
michael@0 | 21 | public: |
michael@0 | 22 | CBaseRecordVector(size_t itemSize): |
michael@0 | 23 | _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} |
michael@0 | 24 | virtual ~CBaseRecordVector(); |
michael@0 | 25 | int Size() const { return _size; } |
michael@0 | 26 | bool IsEmpty() const { return (_size == 0); } |
michael@0 | 27 | void Reserve(int newCapacity); |
michael@0 | 28 | virtual void Delete(int index, int num = 1); |
michael@0 | 29 | void Clear(); |
michael@0 | 30 | void DeleteFrom(int index); |
michael@0 | 31 | void DeleteBack(); |
michael@0 | 32 | }; |
michael@0 | 33 | |
michael@0 | 34 | template <class T> |
michael@0 | 35 | class CRecordVector: public CBaseRecordVector |
michael@0 | 36 | { |
michael@0 | 37 | public: |
michael@0 | 38 | CRecordVector():CBaseRecordVector(sizeof(T)){}; |
michael@0 | 39 | CRecordVector(const CRecordVector &v): |
michael@0 | 40 | CBaseRecordVector(sizeof(T)) { *this = v;} |
michael@0 | 41 | CRecordVector& operator=(const CRecordVector &v) |
michael@0 | 42 | { |
michael@0 | 43 | Clear(); |
michael@0 | 44 | return (*this += v); |
michael@0 | 45 | } |
michael@0 | 46 | CRecordVector& operator+=(const CRecordVector &v) |
michael@0 | 47 | { |
michael@0 | 48 | int size = v.Size(); |
michael@0 | 49 | Reserve(Size() + size); |
michael@0 | 50 | for(int i = 0; i < size; i++) |
michael@0 | 51 | Add(v[i]); |
michael@0 | 52 | return *this; |
michael@0 | 53 | } |
michael@0 | 54 | int Add(T item) |
michael@0 | 55 | { |
michael@0 | 56 | ReserveOnePosition(); |
michael@0 | 57 | ((T *)_items)[_size] = item; |
michael@0 | 58 | return _size++; |
michael@0 | 59 | } |
michael@0 | 60 | void Insert(int index, T item) |
michael@0 | 61 | { |
michael@0 | 62 | InsertOneItem(index); |
michael@0 | 63 | ((T *)_items)[index] = item; |
michael@0 | 64 | } |
michael@0 | 65 | // T* GetPointer() const { return (T*)_items; } |
michael@0 | 66 | // operator const T *() const { return _items; }; |
michael@0 | 67 | const T& operator[](int index) const { return ((T *)_items)[index]; } |
michael@0 | 68 | T& operator[](int index) { return ((T *)_items)[index]; } |
michael@0 | 69 | const T& Front() const { return operator[](0); } |
michael@0 | 70 | T& Front() { return operator[](0); } |
michael@0 | 71 | const T& Back() const { return operator[](_size - 1); } |
michael@0 | 72 | T& Back() { return operator[](_size - 1); } |
michael@0 | 73 | |
michael@0 | 74 | void Swap(int i, int j) |
michael@0 | 75 | { |
michael@0 | 76 | T temp = operator[](i); |
michael@0 | 77 | operator[](i) = operator[](j); |
michael@0 | 78 | operator[](j) = temp; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | int FindInSorted(const T& item) const |
michael@0 | 82 | { |
michael@0 | 83 | int left = 0, right = Size(); |
michael@0 | 84 | while (left != right) |
michael@0 | 85 | { |
michael@0 | 86 | int mid = (left + right) / 2; |
michael@0 | 87 | const T& midValue = (*this)[mid]; |
michael@0 | 88 | if (item == midValue) |
michael@0 | 89 | return mid; |
michael@0 | 90 | if (item < midValue) |
michael@0 | 91 | right = mid; |
michael@0 | 92 | else |
michael@0 | 93 | left = mid + 1; |
michael@0 | 94 | } |
michael@0 | 95 | return -1; |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | void Sort(int left, int right) |
michael@0 | 99 | { |
michael@0 | 100 | if (right - left < 2) |
michael@0 | 101 | return; |
michael@0 | 102 | Swap(left, (left + right) / 2); |
michael@0 | 103 | int last = left; |
michael@0 | 104 | for (int i = left; i < right; i++) |
michael@0 | 105 | if (operator[](i) < operator[](left)) |
michael@0 | 106 | Swap(++last, i); |
michael@0 | 107 | Swap(left, last); |
michael@0 | 108 | Sort(left, last); |
michael@0 | 109 | Sort(last + 1, right); |
michael@0 | 110 | } |
michael@0 | 111 | void Sort() { Sort(0, Size()); } |
michael@0 | 112 | void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) |
michael@0 | 113 | { |
michael@0 | 114 | if (right - left < 2) |
michael@0 | 115 | return; |
michael@0 | 116 | Swap(left, (left + right) / 2); |
michael@0 | 117 | int last = left; |
michael@0 | 118 | for (int i = left; i < right; i++) |
michael@0 | 119 | if (compare(&operator[](i), &operator[](left), param) < 0) |
michael@0 | 120 | Swap(++last, i); |
michael@0 | 121 | Swap(left, last); |
michael@0 | 122 | Sort(left, last, compare, param); |
michael@0 | 123 | Sort(last + 1, right, compare, param); |
michael@0 | 124 | } |
michael@0 | 125 | |
michael@0 | 126 | void Sort(int (*compare)(const T*, const T*, void *), void *param) |
michael@0 | 127 | { |
michael@0 | 128 | Sort(0, Size(), compare, param); |
michael@0 | 129 | } |
michael@0 | 130 | }; |
michael@0 | 131 | |
michael@0 | 132 | typedef CRecordVector<int> CIntVector; |
michael@0 | 133 | typedef CRecordVector<unsigned int> CUIntVector; |
michael@0 | 134 | typedef CRecordVector<bool> CBoolVector; |
michael@0 | 135 | typedef CRecordVector<unsigned char> CByteVector; |
michael@0 | 136 | typedef CRecordVector<void *> CPointerVector; |
michael@0 | 137 | |
michael@0 | 138 | template <class T> |
michael@0 | 139 | class CObjectVector: public CPointerVector |
michael@0 | 140 | { |
michael@0 | 141 | public: |
michael@0 | 142 | CObjectVector(){}; |
michael@0 | 143 | ~CObjectVector() { Clear(); } |
michael@0 | 144 | CObjectVector(const CObjectVector &objectVector) |
michael@0 | 145 | { *this = objectVector; } |
michael@0 | 146 | CObjectVector& operator=(const CObjectVector &objectVector) |
michael@0 | 147 | { |
michael@0 | 148 | Clear(); |
michael@0 | 149 | return (*this += objectVector); |
michael@0 | 150 | } |
michael@0 | 151 | CObjectVector& operator+=(const CObjectVector &objectVector) |
michael@0 | 152 | { |
michael@0 | 153 | int size = objectVector.Size(); |
michael@0 | 154 | Reserve(Size() + size); |
michael@0 | 155 | for(int i = 0; i < size; i++) |
michael@0 | 156 | Add(objectVector[i]); |
michael@0 | 157 | return *this; |
michael@0 | 158 | } |
michael@0 | 159 | const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } |
michael@0 | 160 | T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } |
michael@0 | 161 | T& Front() { return operator[](0); } |
michael@0 | 162 | const T& Front() const { return operator[](0); } |
michael@0 | 163 | T& Back() { return operator[](_size - 1); } |
michael@0 | 164 | const T& Back() const { return operator[](_size - 1); } |
michael@0 | 165 | int Add(const T& item) |
michael@0 | 166 | { return CPointerVector::Add(new T(item)); } |
michael@0 | 167 | void Insert(int index, const T& item) |
michael@0 | 168 | { CPointerVector::Insert(index, new T(item)); } |
michael@0 | 169 | virtual void Delete(int index, int num = 1) |
michael@0 | 170 | { |
michael@0 | 171 | TestIndexAndCorrectNum(index, num); |
michael@0 | 172 | for(int i = 0; i < num; i++) |
michael@0 | 173 | delete (T *)(((void **)_items)[index + i]); |
michael@0 | 174 | CPointerVector::Delete(index, num); |
michael@0 | 175 | } |
michael@0 | 176 | int Find(const T& item) const |
michael@0 | 177 | { |
michael@0 | 178 | for(int i = 0; i < Size(); i++) |
michael@0 | 179 | if (item == (*this)[i]) |
michael@0 | 180 | return i; |
michael@0 | 181 | return -1; |
michael@0 | 182 | } |
michael@0 | 183 | int FindInSorted(const T& item) const |
michael@0 | 184 | { |
michael@0 | 185 | int left = 0, right = Size(); |
michael@0 | 186 | while (left != right) |
michael@0 | 187 | { |
michael@0 | 188 | int mid = (left + right) / 2; |
michael@0 | 189 | const T& midValue = (*this)[mid]; |
michael@0 | 190 | if (item == midValue) |
michael@0 | 191 | return mid; |
michael@0 | 192 | if (item < midValue) |
michael@0 | 193 | right = mid; |
michael@0 | 194 | else |
michael@0 | 195 | left = mid + 1; |
michael@0 | 196 | } |
michael@0 | 197 | return -1; |
michael@0 | 198 | } |
michael@0 | 199 | int AddToSorted(const T& item) |
michael@0 | 200 | { |
michael@0 | 201 | int left = 0, right = Size(); |
michael@0 | 202 | while (left != right) |
michael@0 | 203 | { |
michael@0 | 204 | int mid = (left + right) / 2; |
michael@0 | 205 | const T& midValue = (*this)[mid]; |
michael@0 | 206 | if (item == midValue) |
michael@0 | 207 | { |
michael@0 | 208 | right = mid + 1; |
michael@0 | 209 | break; |
michael@0 | 210 | } |
michael@0 | 211 | if (item < midValue) |
michael@0 | 212 | right = mid; |
michael@0 | 213 | else |
michael@0 | 214 | left = mid + 1; |
michael@0 | 215 | } |
michael@0 | 216 | Insert(right, item); |
michael@0 | 217 | return right; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | void Sort(int (*compare)(void *const *, void *const *, void *), void *param) |
michael@0 | 221 | { CPointerVector::Sort(compare, param); } |
michael@0 | 222 | |
michael@0 | 223 | static int CompareObjectItems(void *const *a1, void *const *a2, void *param) |
michael@0 | 224 | { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } |
michael@0 | 225 | void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } |
michael@0 | 226 | }; |
michael@0 | 227 | |
michael@0 | 228 | #endif |