SHOGUN
v3.2.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 1999-2009 Soeren Sonnenburg 00008 * Written (W) 1999-2008 Gunnar Raetsch 00009 * Written (W) 2012 Heiko Strathmann 00010 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00011 */ 00012 00013 #ifndef _LIST_H_ 00014 #define _LIST_H_ 00015 00016 #include <shogun/lib/common.h> 00017 #include <shogun/base/SGObject.h> 00018 #include <shogun/base/Parameter.h> 00019 00020 namespace shogun 00021 { 00023 class CListElement :public CSGObject 00024 { 00025 public: 00027 CListElement() 00028 : next(NULL), prev(NULL), data(NULL) 00029 { 00030 init(); 00031 } 00032 00039 CListElement(CSGObject* p_data, 00040 CListElement* p_prev = NULL, 00041 CListElement* p_next = NULL) 00042 { 00043 init(); 00044 00045 this->data = p_data; 00046 this->next = p_next; 00047 this->prev = p_prev; 00048 } 00049 00051 virtual ~CListElement() { data = NULL; } 00052 00054 virtual const char* get_name() const { return "ListElement"; } 00055 00056 private: 00057 void init() 00058 { 00059 m_parameters->add(&data, "data", "Data of this element."); 00060 m_parameters->add((CSGObject**) &next, "next", 00061 "Next element in list."); 00062 m_model_selection_parameters->add((CSGObject**) &next, "next", 00063 "Next element in list."); 00064 m_model_selection_parameters->add(&data, "data", "Data of this element."); 00065 } 00066 00067 public: 00069 CListElement* next; 00071 CListElement* prev; 00073 CSGObject* data; 00074 00075 }; 00076 00082 class CList : public CSGObject 00083 { 00084 public: 00089 CList(bool p_delete_data=false) : CSGObject() 00090 { 00091 m_parameters->add(&delete_data, "delete_data", 00092 "Delete data on destruction?"); 00093 m_parameters->add(&num_elements, "num_elements", 00094 "Number of elements."); 00095 m_parameters->add((CSGObject**) &first, "first", 00096 "First element in list."); 00097 m_model_selection_parameters->add((CSGObject**) &first, "first", 00098 "First element in list."); 00099 00100 first = NULL; 00101 current = NULL; 00102 last = NULL; 00103 00104 num_elements = 0; 00105 this->delete_data=p_delete_data; 00106 } 00107 00108 virtual ~CList() 00109 { 00110 SG_DEBUG("Destroying List %p\n", this) 00111 00112 delete_all_elements(); 00113 } 00114 00116 inline void delete_all_elements() 00117 { 00118 while (get_num_elements()) 00119 { 00120 CSGObject* d=delete_element(); 00121 00122 if (delete_data) 00123 { 00124 SG_DEBUG("SG_UNREF List Element %p\n", d) 00125 SG_UNREF(d); 00126 } 00127 } 00128 00129 first=NULL; 00130 current=NULL; 00131 last=NULL; 00132 } 00133 00138 inline int32_t get_num_elements() { return num_elements; } 00139 00144 inline CSGObject* get_first_element() 00145 { 00146 if (first != NULL) 00147 { 00148 current = first; 00149 if (delete_data) 00150 SG_REF(current->data); 00151 return current->data; 00152 } 00153 else 00154 return NULL; 00155 } 00156 00161 inline CSGObject* get_last_element() 00162 { 00163 if (last != NULL) 00164 { 00165 current = last; 00166 if (delete_data) 00167 SG_REF(current->data); 00168 return current->data; 00169 } 00170 else 00171 return NULL; 00172 } 00173 00178 inline CSGObject* get_next_element() 00179 { 00180 if ((current != NULL) && (current->next != NULL)) 00181 { 00182 current = current->next; 00183 if (delete_data) 00184 SG_REF(current->data); 00185 return current->data; 00186 } 00187 else 00188 return NULL; 00189 } 00190 00195 inline CSGObject* get_previous_element() 00196 { 00197 if ((current != NULL) && (current->prev != NULL)) 00198 { 00199 current = current->prev; 00200 if (delete_data) 00201 SG_REF(current->data); 00202 return current->data; 00203 } 00204 else 00205 return NULL; 00206 } 00207 00212 inline CSGObject* get_current_element() 00213 { 00214 if (current != NULL) 00215 { 00216 if (delete_data) 00217 SG_REF(current->data); 00218 return current->data; 00219 } 00220 else 00221 return NULL; 00222 } 00223 00224 00227 00233 inline CSGObject* get_first_element(CListElement*& p_current) 00234 { 00235 if (first != NULL) 00236 { 00237 p_current = first; 00238 if (delete_data) 00239 SG_REF(p_current->data); 00240 return p_current->data; 00241 } 00242 else 00243 return NULL; 00244 } 00245 00251 inline CSGObject* get_last_element(CListElement*& p_current) 00252 { 00253 if (last != NULL) 00254 { 00255 p_current = last; 00256 if (delete_data) 00257 SG_REF(p_current->data); 00258 return p_current->data; 00259 } 00260 else 00261 return NULL; 00262 } 00263 00269 inline CSGObject* get_next_element(CListElement*& p_current) 00270 { 00271 if ((p_current != NULL) && (p_current->next != NULL)) 00272 { 00273 p_current = p_current->next; 00274 if (delete_data) 00275 SG_REF(p_current->data); 00276 return p_current->data; 00277 } 00278 else 00279 return NULL; 00280 } 00281 00287 inline CSGObject* get_previous_element(CListElement*& p_current) 00288 { 00289 if ((p_current != NULL) && (p_current->prev != NULL)) 00290 { 00291 p_current = p_current->prev; 00292 if (delete_data) 00293 SG_REF(p_current->data); 00294 return p_current->data; 00295 } 00296 else 00297 return NULL; 00298 } 00299 00305 inline CSGObject* get_current_element(CListElement*& p_current) 00306 { 00307 if (p_current != NULL) 00308 { 00309 if (delete_data) 00310 SG_REF(p_current->data); 00311 return p_current->data; 00312 } 00313 else 00314 return NULL; 00315 } 00317 00323 inline bool append_element(CSGObject* data) 00324 { 00325 if (current != NULL) // none available, case is shattered in insert_element() 00326 { 00327 CSGObject* e=get_next_element(); 00328 if (e) 00329 { 00330 if (delete_data) 00331 SG_UNREF(e); 00332 // if successor exists use insert_element() 00333 return insert_element(data); 00334 } 00335 else 00336 { 00337 // case with no successor but nonempty 00338 CListElement* element; 00339 00340 if ((element = new CListElement(data, current)) != NULL) 00341 { 00342 current->next = element; 00343 current = element; 00344 last = element; 00345 00346 num_elements++; 00347 00348 if (delete_data) 00349 SG_REF(data); 00350 00351 return true; 00352 } 00353 else 00354 return false; 00355 } 00356 } 00357 else 00358 return insert_element(data); 00359 } 00360 00366 inline bool append_element_at_listend(CSGObject* data) 00367 { 00368 CSGObject* p = get_last_element(); 00369 if (delete_data) 00370 SG_UNREF(p); 00371 00372 return append_element(data); 00373 } 00374 00380 inline bool push(CSGObject* data) 00381 { 00382 return append_element_at_listend(data); 00383 } 00384 00389 inline bool pop() 00390 { 00391 if (last) 00392 { 00393 if (first==last) 00394 first=NULL; 00395 00396 if (current==last) 00397 { 00398 if (first==last) 00399 current=NULL; 00400 else 00401 current=current->prev; 00402 } 00403 00404 if (delete_data) 00405 SG_UNREF(last->data); 00406 00407 CListElement* temp=last; 00408 last=last->prev; 00409 SG_UNREF(temp); 00410 if (last) 00411 last->next=NULL; 00412 00413 num_elements--; 00414 00415 return true; 00416 } 00417 else 00418 return false; 00419 } 00420 00426 inline bool insert_element(CSGObject* data) 00427 { 00428 CListElement* element; 00429 00430 if (delete_data) 00431 SG_REF(data); 00432 00433 if (current == NULL) 00434 { 00435 if ((element = new CListElement(data)) != NULL) 00436 { 00437 current = element; 00438 first = element; 00439 last = element; 00440 00441 num_elements++; 00442 00443 return true; 00444 } 00445 else 00446 return false; 00447 } 00448 else 00449 { 00450 if ((element = new CListElement(data, current->prev, current)) != NULL) 00451 { 00452 if (current->prev != NULL) 00453 current->prev->next = element; 00454 else 00455 first = element; 00456 00457 current->prev = element; 00458 current = element; 00459 00460 num_elements++; 00461 00462 return true; 00463 } 00464 else 00465 return false; 00466 } 00467 } 00468 00475 inline CSGObject* delete_element() 00476 { 00477 CSGObject* data = get_current_element(); 00478 00479 if (num_elements>0) 00480 num_elements--; 00481 00482 if (data) 00483 { 00484 if (delete_data) 00485 SG_UNREF(data); 00486 00487 CListElement *element = current; 00488 00489 if (element->prev) 00490 element->prev->next = element->next; 00491 00492 if (element->next) 00493 element->next->prev = element->prev; 00494 00495 if (element->next) 00496 current = element->next; 00497 else 00498 current = element->prev; 00499 00500 if (element == first) 00501 first = element->next; 00502 00503 if (element == last) 00504 last = element->prev; 00505 00506 delete element; 00507 00508 return data; 00509 } 00510 00511 return NULL; 00512 } 00513 00514 virtual void load_serializable_post() throw (ShogunException) 00515 { 00516 CSGObject::load_serializable_post(); 00517 00518 current = first; 00519 CListElement* prev = NULL; 00520 for (CListElement* cur=first; cur!=NULL; cur=cur->next) 00521 { 00522 cur->prev = prev; 00523 prev = cur; 00524 } 00525 last = prev; 00526 } 00527 00529 void print_list() 00530 { 00531 CListElement* c=first; 00532 00533 while (c) 00534 { 00535 SG_PRINT("\"%s\" at %p\n", c->data ? c->data->get_name() : "", c->data) 00536 c=c->next; 00537 } 00538 } 00539 00541 inline bool get_delete_data() { return delete_data; } 00542 00544 virtual const char* get_name() const { return "List"; } 00545 00546 private: 00548 bool delete_data; 00550 CListElement* first; 00552 CListElement* current; 00554 CListElement* last; 00556 int32_t num_elements; 00557 }; 00558 } 00559 #endif