00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00037 template<class T> class pgBuf
00038 {
00039 public:
00040 pgDefineException(ExceptionInvalidArgument);
00041 pgDefineException(ExceptionNotInitialized);
00042 pgDefineException(ExceptionOutOfBuffer);
00043
00047 pgBuf()
00048 {
00049 m_elem = NULL;
00050 m_state = NULL;
00051 m_index_tbl = NULL;
00052 m_size = m_used_size = 0;
00053 }
00054
00058 ~pgBuf()
00059 {
00060 if (m_elem)
00061 {
00062 for (s32 i = 0; i < m_size; i++)
00063 {
00064 if (m_state[i] == STATE_USED)
00065 {
00066 m_elem[i].~T();
00067 }
00068 }
00069
00070 pgFree(m_elem);
00071 pgDeleteArray(m_state, u8);
00072 pgDeleteArray(m_index_tbl, u16);
00073 }
00074 }
00075
00080 void init(u16 size)
00081 {
00082 if (size == 0)
00083 {
00084 pgThrow(ExceptionInvalidArgument);
00085 }
00086
00087 this->~pgBuf();
00088
00089 m_size = size;
00090 m_used_size = 0;
00091
00092 m_elem = static_cast<T*>(pgMalloc(sizeof(T) * m_size));
00093 pgNewArray(m_state, u8, m_size);
00094 pgNewArray(m_index_tbl, u16, m_size);
00095
00096 for (s32 i = 0; i < m_size; i++)
00097 {
00098 m_state[i] = STATE_FREE;
00099 m_index_tbl[i] = i;
00100 }
00101 }
00102
00107 u16 getSize() const
00108 {
00109 return m_size;
00110 }
00111
00116 u16 getUsedSize() const
00117 {
00118 return m_used_size;
00119 }
00120
00125 u16 getFreeSize() const
00126 {
00127 return m_size - m_used_size;
00128 }
00129
00135 T* getFirstN() const
00136 {
00137 if (!m_elem)
00138 {
00139 pgThrow(ExceptionNotInitialized);
00140 }
00141
00142 for (s32 i = 0; i < m_size; i++)
00143 {
00144 if (m_state[i] == STATE_USED)
00145 {
00146 return &m_elem[i];
00147 }
00148 }
00149
00150 return NULL;
00151 }
00152
00158 T* getLastN() const
00159 {
00160 if (!m_elem)
00161 {
00162 pgThrow(ExceptionNotInitialized);
00163 }
00164
00165 for (s32 i = m_size - 1; i >= 0; i--)
00166 {
00167 if (m_state[i] == STATE_USED)
00168 {
00169 return &m_elem[i];
00170 }
00171 }
00172
00173 return NULL;
00174 }
00175
00182 T* getPrevN(const T* elem) const
00183 {
00184 if (!m_elem)
00185 {
00186 pgThrow(ExceptionNotInitialized);
00187 }
00188
00189 if (elem < m_elem || elem >= m_elem + m_size)
00190 {
00191 pgThrow(ExceptionInvalidArgument);
00192 }
00193
00194 u16 index = static_cast<u16>(elem - m_elem);
00195
00196 if (m_state[index] == STATE_FREE)
00197 {
00198 pgThrow(ExceptionInvalidArgument);
00199 }
00200
00201 if (index > 0)
00202 {
00203 for (s32 i = index - 1; i >= 0; i--)
00204 {
00205 if (m_state[i] == STATE_USED)
00206 {
00207 return &m_elem[i];
00208 }
00209 }
00210 }
00211
00212 return NULL;
00213 }
00214
00221 T* getNextN(const T* elem) const
00222 {
00223 if (!m_elem)
00224 {
00225 pgThrow(ExceptionNotInitialized);
00226 }
00227
00228 if (elem < m_elem || elem >= m_elem + m_size)
00229 {
00230 pgThrow(ExceptionInvalidArgument);
00231 }
00232
00233 u16 index = static_cast<u16>(elem - m_elem);
00234
00235 if (m_state[index] == STATE_FREE)
00236 {
00237 pgThrow(ExceptionInvalidArgument);
00238 }
00239
00240 if (index + 1 < m_size)
00241 {
00242 for (s32 i = index + 1; i < m_size; i++)
00243 {
00244 if (m_state[i] == STATE_USED)
00245 {
00246 return &m_elem[i];
00247 }
00248 }
00249 }
00250
00251 return NULL;
00252 }
00253
00258 T* newElement()
00259 {
00260 if (!m_elem)
00261 {
00262 pgThrow(ExceptionNotInitialized);
00263 }
00264
00265 if (m_used_size >= m_size)
00266 {
00267 pgThrow(ExceptionOutOfBuffer);
00268 }
00269
00270 u16 index = m_index_tbl[m_used_size];
00271
00272 m_state[index] = STATE_USED;
00273
00274 m_used_size++;
00275
00276 T* elem = &m_elem[index];
00277 new(elem, NULL) T;
00278
00279 return elem;
00280 }
00281
00286 void deleteElement(T* elem)
00287 {
00288 if (!m_elem)
00289 {
00290 pgThrow(ExceptionNotInitialized);
00291 }
00292
00293 if (elem < m_elem || elem >= m_elem + m_size)
00294 {
00295 pgThrow(ExceptionInvalidArgument);
00296 }
00297
00298 u16 index = static_cast<u16>(elem - m_elem);
00299
00300 if (m_state[index] == STATE_FREE)
00301 {
00302 pgThrow(ExceptionInvalidArgument);
00303 }
00304
00305 elem->~T();
00306
00307 m_used_size--;
00308
00309 m_index_tbl[m_used_size] = index;
00310 m_state[index] = STATE_FREE;
00311 }
00312
00316 void clear()
00317 {
00318 if (!m_elem)
00319 {
00320 pgThrow(ExceptionNotInitialized);
00321 }
00322
00323 m_used_size = 0;
00324
00325 for (s32 i = 0; i < m_size; i++)
00326 {
00327 if (m_state[i] == STATE_USED)
00328 {
00329 m_elem[i].~T();
00330 m_state[i] = STATE_FREE;
00331 }
00332
00333 m_index_tbl[i] = i;
00334 }
00335 }
00336
00337 private:
00338 enum ElemState
00339 {
00340 STATE_FREE,
00341 STATE_USED
00342 };
00343
00344 pgBuf(const pgBuf<T>&) {}
00345 void operator=(const pgBuf<T>&) {}
00346
00347 T* m_elem;
00348 u8* m_state;
00349 u16* m_index_tbl;
00350 u16 m_size;
00351 u16 m_used_size;
00352 };