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
00038 template<class K, class D> class pgMap
00039 {
00040 public:
00041 pgDefineException(ExceptionInvalidArgument);
00042 pgDefineException(ExceptionNotFound);
00043 pgDefineException(ExceptionNotInitialized);
00044 pgDefineException(ExceptionSameKeyExists);
00045
00049 pgMap()
00050 {
00051 m_hash_list = NULL;
00052 m_last_item1 = m_last_item2 = m_last_item3 = NULL;
00053 m_hash_size = 0;
00054 m_data_num = 0;
00055 }
00056
00060 ~pgMap()
00061 {
00062 clear();
00063
00064 if (m_hash_list)
00065 {
00066 pgDeleteArray(m_hash_list, pgList<MapItem>);
00067 }
00068 }
00069
00075 void init(u16 hash_size)
00076 {
00077 if (hash_size == 0)
00078 {
00079 pgThrow(ExceptionInvalidArgument);
00080 }
00081
00082 clear();
00083
00084 if (m_hash_list)
00085 {
00086 pgDeleteArray(m_hash_list, pgList<MapItem>);
00087 }
00088
00089 m_hash_size = hash_size;
00090 pgNewArray(m_hash_list, pgList<MapItem>, m_hash_size);
00091 }
00092
00097 u16 getHashSize() const
00098 {
00099 return m_hash_size;
00100 }
00101
00106 u16 getDataNum() const
00107 {
00108 return m_data_num;
00109 }
00110
00116 D* get(K key)
00117 {
00118 D* data = getN(key);
00119
00120 if (!data)
00121 {
00122 pgThrow(ExceptionNotFound);
00123 }
00124
00125 return data;
00126 }
00127
00134 D* getN(K key)
00135 {
00136 if (!m_hash_list)
00137 {
00138 pgThrow(ExceptionNotInitialized);
00139 }
00140
00141 if (m_last_item1 && m_last_item1->key == key)
00142 {
00143 return &m_last_item1->data;
00144 }
00145 else if (m_last_item2 && m_last_item2->key == key)
00146 {
00147 MapItem* item = m_last_item1;
00148 m_last_item1 = m_last_item2;
00149 m_last_item2 = item;
00150
00151 return &m_last_item1->data;
00152 }
00153 else if (m_last_item3 && m_last_item3->key == key)
00154 {
00155 MapItem* item = m_last_item1;
00156 m_last_item1 = m_last_item3;
00157 m_last_item3 = m_last_item2;
00158 m_last_item2 = item;
00159
00160 return &m_last_item1->data;
00161 }
00162 else
00163 {
00164 s32 index = key % m_hash_size;
00165 pgList<MapItem>* hash_list = &m_hash_list[(index < 0) ? -index : index];
00166
00167 for (typename pgList<MapItem>::Item* item = hash_list->getFirstN(); item; item = item->getNextN())
00168 {
00169 if (item->getSelf()->key == key)
00170 {
00171 m_last_item3 = m_last_item2;
00172 m_last_item2 = m_last_item1;
00173 m_last_item1 = item->getSelf();
00174
00175 hash_list->addFirst(item);
00176
00177 return &m_last_item1->data;
00178 }
00179 }
00180
00181 return NULL;
00182 }
00183 }
00184
00190 void add(K key, const D& data)
00191 {
00192 if (!m_hash_list)
00193 {
00194 pgThrow(ExceptionNotInitialized);
00195 }
00196
00197 if (getN(key))
00198 {
00199 pgThrow(ExceptionSameKeyExists);
00200 }
00201
00202 MapItem* new_item = pgNew(MapItem);
00203
00204 new_item->order_item.init(new_item);
00205 new_item->hash_item.init(new_item);
00206 new_item->key = key;
00207 new_item->data = data;
00208
00209 m_order_list.addLast(&new_item->order_item);
00210
00211 s32 index = key % m_hash_size;
00212 m_hash_list[(index < 0) ? -index : index].addLast(&new_item->hash_item);
00213
00214 m_data_num++;
00215 }
00216
00221 void remove(K key)
00222 {
00223 if (!m_hash_list)
00224 {
00225 pgThrow(ExceptionNotInitialized);
00226 }
00227
00228 if (m_last_item1 && m_last_item1->key == key)
00229 {
00230 pgDelete(m_last_item1, MapItem);
00231 m_data_num--;
00232
00233 m_last_item1 = m_last_item2;
00234 m_last_item2 = m_last_item3;
00235 m_last_item3 = NULL;
00236 }
00237 else if (m_last_item2 && m_last_item2->key == key)
00238 {
00239 pgDelete(m_last_item2, MapItem);
00240 m_data_num--;
00241
00242 m_last_item2 = m_last_item3;
00243 m_last_item3 = NULL;
00244 }
00245 else if (m_last_item3 && m_last_item3->key == key)
00246 {
00247 pgDelete(m_last_item3, MapItem);
00248 m_data_num--;
00249
00250 m_last_item3 = NULL;
00251 }
00252 else
00253 {
00254 s32 index = key % m_hash_size;
00255 pgList<MapItem>* hash_list = &m_hash_list[(index < 0) ? -index : index];
00256
00257 for (typename pgList<MapItem>::Item* item = hash_list->getFirstN(); item; item = item->getNextN())
00258 {
00259 if (item->getSelf()->key == key)
00260 {
00261 pgDelete(item->getSelf(), MapItem);
00262 m_data_num--;
00263
00264 return;
00265 }
00266 }
00267
00268 pgThrow(ExceptionNotFound);
00269 }
00270 }
00271
00275 void clear()
00276 {
00277 m_order_list.clear();
00278
00279 if (m_hash_list)
00280 {
00281 for (s32 i = 0; i < m_hash_size; i++)
00282 {
00283 pgList<MapItem>* hash_list = &m_hash_list[i];
00284
00285 while (hash_list->hasItem())
00286 {
00287 pgDelete(hash_list->getFirstN()->getSelf(), MapItem);
00288 }
00289 }
00290
00291 m_last_item1 = m_last_item2 = m_last_item3 = NULL;
00292 m_data_num = 0;
00293 }
00294 }
00295
00300 const K* getFirstKeyN() const
00301 {
00302 if (!m_hash_list)
00303 {
00304 pgThrow(ExceptionNotInitialized);
00305 }
00306
00307 return m_order_list.hasItem() ? &m_order_list.getFirstN()->getSelf()->key : NULL;
00308 }
00309
00314 const K* getLastKeyN() const
00315 {
00316 if (!m_hash_list)
00317 {
00318 pgThrow(ExceptionNotInitialized);
00319 }
00320
00321 return m_order_list.hasItem() ? &m_order_list.getLastN()->getSelf()->key : NULL;
00322 }
00323
00330 const K* getPrevKeyN(K key)
00331 {
00332 pgTry
00333 {
00334 typename pgList<MapItem>::Item* prev = reinterpret_cast<MapItem*>(get(key))->order_item.getPrevN();
00335
00336 return prev ? &prev->getSelf()->key : NULL;
00337 }
00338 pgCatch(ExceptionNotFound)
00339 {
00340 pgThrow(ExceptionInvalidArgument);
00341 }
00342
00343 return NULL;
00344 }
00345
00352 const K* getNextKeyN(K key)
00353 {
00354 pgTry
00355 {
00356 typename pgList<MapItem>::Item* next = reinterpret_cast<MapItem*>(get(key))->order_item.getNextN();
00357
00358 return next ? &next->getSelf()->key : NULL;
00359 }
00360 pgCatch(ExceptionNotFound)
00361 {
00362 pgThrow(ExceptionInvalidArgument);
00363 }
00364
00365 return NULL;
00366 }
00367
00372 void moveFirst(K key)
00373 {
00374 pgTry
00375 {
00376 typename pgList<MapItem>::Item* item = &reinterpret_cast<MapItem*>(get(key))->order_item;
00377
00378 m_order_list.addFirst(item);
00379 }
00380 pgCatch(ExceptionNotFound)
00381 {
00382 pgThrow(ExceptionInvalidArgument);
00383 }
00384 }
00385
00390 void moveLast(K key)
00391 {
00392 pgTry
00393 {
00394 typename pgList<MapItem>::Item* item = &reinterpret_cast<MapItem*>(get(key))->order_item;
00395
00396 m_order_list.addLast(item);
00397 }
00398 pgCatch(ExceptionNotFound)
00399 {
00400 pgThrow(ExceptionInvalidArgument);
00401 }
00402 }
00403
00409 void moveBefore(K key, K next_key)
00410 {
00411 pgTry
00412 {
00413 typename pgList<MapItem>::Item* item = &reinterpret_cast<MapItem*>(get(key))->order_item;
00414 typename pgList<MapItem>::Item* next = &reinterpret_cast<MapItem*>(get(next_key))->order_item;
00415
00416 item->joinBefore(next);
00417 }
00418 pgCatch(ExceptionNotFound)
00419 {
00420 pgThrow(ExceptionInvalidArgument);
00421 }
00422 }
00423
00429 void moveAfter(K key, K prev_key)
00430 {
00431 pgTry
00432 {
00433 typename pgList<MapItem>::Item* item = &reinterpret_cast<MapItem*>(get(key))->order_item;
00434 typename pgList<MapItem>::Item* prev = &reinterpret_cast<MapItem*>(get(prev_key))->order_item;
00435
00436 item->joinAfter(prev);
00437 }
00438 pgCatch(ExceptionNotFound)
00439 {
00440 pgThrow(ExceptionInvalidArgument);
00441 }
00442 }
00443
00444 private:
00445 struct MapItem
00446 {
00447 D data;
00448 typename pgList<MapItem>::Item order_item;
00449 typename pgList<MapItem>::Item hash_item;
00450 K key;
00451 };
00452
00453 pgMap(const pgMap<K, D>&) {}
00454 void operator=(const pgMap<K, D>&) {}
00455
00456 pgList<MapItem> m_order_list;
00457 pgList<MapItem>* m_hash_list;
00458 MapItem* m_last_item1;
00459 MapItem* m_last_item2;
00460 MapItem* m_last_item3;
00461 u16 m_hash_size;
00462 u16 m_data_num;
00463 };