SHOGUN  3.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
List.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 1999-2009 Soeren Sonnenburg
8  * Written (W) 1999-2008 Gunnar Raetsch
9  * Written (W) 2012 Heiko Strathmann
10  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
11  */
12 
13 #ifndef _LIST_H_
14 #define _LIST_H_
15 
16 #include <shogun/lib/config.h>
17 
18 #include <shogun/lib/common.h>
19 #include <shogun/base/SGObject.h>
20 #include <shogun/base/Parameter.h>
21 
22 namespace shogun
23 {
25 class CListElement :public CSGObject
26 {
27  public:
30  : next(NULL), prev(NULL), data(NULL)
31  {
32  init();
33  }
34 
42  CListElement* p_prev = NULL,
43  CListElement* p_next = NULL)
44  {
45  init();
46 
47  this->data = p_data;
48  this->next = p_next;
49  this->prev = p_prev;
50  }
51 
53  virtual ~CListElement() { data = NULL; }
54 
56  virtual const char* get_name() const { return "ListElement"; }
57 
58  private:
59  void init()
60  {
61  m_parameters->add(&data, "data", "Data of this element.");
62  m_parameters->add((CSGObject**) &next, "next",
63  "Next element in list.");
65  "Next element in list.");
66  m_model_selection_parameters->add(&data, "data", "Data of this element.");
67  }
68 
69  public:
76 
77 };
78 
84 class CList : public CSGObject
85 {
86  public:
91  CList(bool p_delete_data=false) : CSGObject()
92  {
93  m_parameters->add(&delete_data, "delete_data",
94  "Delete data on destruction?");
95  m_parameters->add(&num_elements, "num_elements",
96  "Number of elements.");
97  m_parameters->add((CSGObject**) &first, "first",
98  "First element in list.");
99  m_model_selection_parameters->add((CSGObject**) &first, "first",
100  "First element in list.");
101 
102  first = NULL;
103  current = NULL;
104  last = NULL;
105 
106  num_elements = 0;
107  this->delete_data=p_delete_data;
108  }
109 
110  virtual ~CList()
111  {
112  SG_DEBUG("Destroying List %p\n", this)
113 
115  }
116 
118  inline void delete_all_elements()
119  {
120  // move to the first element and then delete sequentially
122 
123  // important to unref because get_first_elements() SG_REFs it
124  if (delete_data)
125  SG_UNREF(d);
126 
127  while (get_num_elements())
128  {
129  d=delete_element();
130 
131  // we don't need to check for delete_data flag here
132  // delete_element() takes care of whether or not
133  // data should be SG_UNREF'ed
134  }
135 
136  first=NULL;
137  current=NULL;
138  last=NULL;
139  }
140 
145  inline int32_t get_num_elements() { return num_elements; }
146 
152  {
153  if (first != NULL)
154  {
155  current = first;
156  if (delete_data)
157  SG_REF(current->data);
158  return current->data;
159  }
160  else
161  return NULL;
162  }
163 
169  {
170  if (last != NULL)
171  {
172  current = last;
173  if (delete_data)
174  SG_REF(current->data);
175  return current->data;
176  }
177  else
178  return NULL;
179  }
180 
186  {
187  if ((current != NULL) && (current->next != NULL))
188  {
189  current = current->next;
190  if (delete_data)
191  SG_REF(current->data);
192  return current->data;
193  }
194  else
195  return NULL;
196  }
197 
203  {
204  if ((current != NULL) && (current->prev != NULL))
205  {
206  current = current->prev;
207  if (delete_data)
208  SG_REF(current->data);
209  return current->data;
210  }
211  else
212  return NULL;
213  }
214 
220  {
221  if (current != NULL)
222  {
223  if (delete_data)
224  SG_REF(current->data);
225  return current->data;
226  }
227  else
228  return NULL;
229  }
230 
231 
234 
241  {
242  if (first != NULL)
243  {
244  p_current = first;
245  if (delete_data)
246  SG_REF(p_current->data);
247  return p_current->data;
248  }
249  else
250  return NULL;
251  }
252 
259  {
260  if (last != NULL)
261  {
262  p_current = last;
263  if (delete_data)
264  SG_REF(p_current->data);
265  return p_current->data;
266  }
267  else
268  return NULL;
269  }
270 
277  {
278  if ((p_current != NULL) && (p_current->next != NULL))
279  {
280  p_current = p_current->next;
281  if (delete_data)
282  SG_REF(p_current->data);
283  return p_current->data;
284  }
285  else
286  return NULL;
287  }
288 
295  {
296  if ((p_current != NULL) && (p_current->prev != NULL))
297  {
298  p_current = p_current->prev;
299  if (delete_data)
300  SG_REF(p_current->data);
301  return p_current->data;
302  }
303  else
304  return NULL;
305  }
306 
313  {
314  if (p_current != NULL)
315  {
316  if (delete_data)
317  SG_REF(p_current->data);
318  return p_current->data;
319  }
320  else
321  return NULL;
322  }
324 
331  inline bool append_element(CSGObject* data)
332  {
333  SG_DEBUG("Entering\n");
334 
335  // none available, case is shattered in insert_element()
336  if (current != NULL)
337  {
339  if (e)
340  {
341  if (delete_data)
342  SG_UNREF(e);
343  // if successor exists use insert_element()
344  SG_DEBUG("Leaving\n");
345  return insert_element(data);
346  }
347  else
348  {
349  // case with no successor but nonempty
350  CListElement* element;
351 
352  if ((element = new CListElement(data, current)) != NULL)
353  {
354  current->next = element;
355  current = element;
356  last = element;
357 
358  num_elements++;
359 
360  if (delete_data)
361  SG_REF(data);
362 
363  SG_DEBUG("Leaving\n");
364  return true;
365  }
366  else
367  {
368  SG_WARNING("Error in allocating memory for new element!\n");
369  SG_DEBUG("Leaving\n");
370  return false;
371  }
372  }
373  }
374  else
375  {
376  SG_DEBUG("Leaving\n");
377  return insert_element(data);
378  }
379  }
380 
387  {
389  if (delete_data)
390  SG_UNREF(p);
391 
392  return append_element(data);
393  }
394 
400  inline bool push(CSGObject* data)
401  {
402  return append_element_at_listend(data);
403  }
404 
409  inline bool pop()
410  {
411  if (last)
412  {
413  if (first==last)
414  first=NULL;
415 
416  if (current==last)
417  {
418  if (first==last)
419  current=NULL;
420  else
421  current=current->prev;
422  }
423 
424  if (delete_data)
425  SG_UNREF(last->data);
426 
427  CListElement* temp=last;
428  last=last->prev;
429  SG_UNREF(temp);
430  if (last)
431  last->next=NULL;
432 
433  num_elements--;
434 
435  return true;
436  }
437  else
438  return false;
439  }
440 
447  inline bool insert_element(CSGObject* data)
448  {
449  CListElement* element;
450 
451  if (delete_data)
452  SG_REF(data);
453 
454  if (current == NULL)
455  {
456  if ((element = new CListElement(data)) != NULL)
457  {
458  current = element;
459  first = element;
460  last = element;
461 
462  num_elements++;
463 
464  return true;
465  }
466  else
467  {
468  SG_WARNING("Error in allocating memory for new element!\n");
469  return false;
470  }
471  }
472  else
473  {
474  if ((element = new CListElement(data, current->prev, current)) != NULL)
475  {
476  if (current->prev != NULL)
477  current->prev->next = element;
478  else
479  first = element;
480 
481  current->prev = element;
482  current = element;
483 
484  num_elements++;
485 
486  return true;
487  }
488  else
489  {
490  SG_WARNING("Error in allocating memory for new element!\n");
491  return false;
492  }
493  }
494  }
495 
503  {
504  SG_DEBUG("Entering\n");
505  CSGObject* data = current ? current->data : NULL;
506 
507  if (num_elements>0)
508  num_elements--;
509 
510  if (data)
511  {
512  if (delete_data)
513  {
514  SG_GCDEBUG("Decreasing refcount of %s(%p)!\n",
515  data->get_name(), data);
516  SG_UNREF(data);
517  }
518 
519  CListElement *element = current;
520 
521  if (element->prev)
522  element->prev->next = element->next;
523 
524  if (element->next)
525  element->next->prev = element->prev;
526 
527  if (element->next)
528  current = element->next;
529  else
530  current = element->prev;
531 
532  if (element == first)
533  first = element->next;
534 
535  if (element == last)
536  last = element->prev;
537 
538  delete element;
539 
540  SG_DEBUG("Leaving\n");
541  return data;
542  }
543 
544  SG_DEBUG("Leaving\n");
545  return NULL;
546  }
547 
549  {
551 
552  current = first;
553  CListElement* prev = NULL;
554  for (CListElement* cur=first; cur!=NULL; cur=cur->next)
555  {
556  cur->prev = prev;
557  prev = cur;
558  }
559  last = prev;
560  }
561 
563  void print_list()
564  {
565  CListElement* c=first;
566 
567  while (c)
568  {
569  SG_PRINT("\"%s\" at %p\n", c->data ? c->data->get_name() : "", c->data)
570  c=c->next;
571  }
572  }
573 
575  inline bool get_delete_data() { return delete_data; }
576 
578  virtual const char* get_name() const { return "List"; }
579 
580  private:
582  bool delete_data;
584  CListElement* first;
586  CListElement* current;
588  CListElement* last;
590  int32_t num_elements;
591 };
592 }
593 #endif

SHOGUN Machine Learning Toolbox - Documentation