libcsdbg  1.28
C++ exception (and generic) stack trace debug library
stack.hpp
Go to the documentation of this file.
1 #ifndef _CSDBG_STACK
2 #define _CSDBG_STACK 1
3 
10 #include "./node.hpp"
11 #include "./exception.hpp"
12 
13 namespace csdbg {
14 
27 template <class T>
28 class stack: virtual public object
29 {
30 protected:
31 
32  /* Protected variables */
33 
39  /* Protected generic methods */
40 
41  virtual node<T>* node_at(u32 i) const;
42 
43  virtual node<T>* node_with(const T*) const;
44 
45 public:
46 
47  /* Constructors, copy constructors and destructor */
48 
49  stack();
50 
51  stack(const stack&);
52 
53  virtual ~stack();
54 
55  virtual stack* clone() const;
56 
57 
58  /* Accessor methods */
59 
60  virtual u32 size() const;
61 
62 
63  /* Operator overloading methods */
64 
65  virtual stack& operator=(const stack&);
66 
67  virtual T* operator[](u32) const;
68 
69 
70  /* Generic methods */
71 
72  virtual stack& push(T*);
73 
74  virtual stack& pop();
75 
76  virtual stack& clear();
77 
78  virtual T* peek(u32) const;
79 
80  virtual stack& foreach(void (*)(u32, T*)) const;
81 };
82 
83 
93 template <class T>
95 {
96  if ( unlikely(i >= m_size) )
97  throw exception("offset out of stack bounds (%d >= %d)", i, m_size);
98 
99  node<T> *n = m_top;
100  while ( likely(i-- > 0) )
101  n = n->m_link;
102 
103  return n;
104 }
105 
106 
114 template <class T>
115 node<T>* stack<T>::node_with(const T *d) const
116 {
117  __D_ASSERT(d != NULL);
118  if ( unlikely(d == NULL) )
119  return NULL;
120 
121  for (node<T> *n = m_top; likely(n != NULL); n = n->m_link)
122  if ( unlikely(n->m_data == d) )
123  return n;
124 
125  return NULL;
126 }
127 
128 
132 template <class T>
134 m_top(NULL),
135 m_size(0)
136 {
137 }
138 
139 
147 template <class T>
148 inline stack<T>::stack(const stack &src)
149 try:
150 m_top(NULL),
151 m_size(0)
152 {
153  *this = src;
154 }
155 
156 catch (...) {
157  clear();
158 }
159 
160 
164 template <class T>
166 {
167  clear();
168 }
169 
170 
178 template <class T>
179 inline stack<T>* stack<T>::clone() const
180 {
181  return new stack(*this);
182 }
183 
184 
190 template <class T>
191 inline u32 stack<T>::size() const
192 {
193  return m_size;
194 }
195 
196 
210 template <class T>
212 {
213  if ( unlikely(this == &rval) )
214  return *this;
215 
216  /* Check if the stacks overlap and detach shared data pointers */
217  for (node<T> *n = m_top; likely(n != NULL); n = n->m_link)
218  if ( unlikely(rval.node_with(n->m_data) != NULL) )
219  n->detach();
220 
221  clear();
222  for (node<T> *n = rval.m_top; likely(n != NULL); n = n->m_link) {
223  T *copy = NULL;
224  try {
225  copy = new T(*n->m_data);
226  push(copy);
227  }
228 
229  catch (...) {
230  delete copy;
231  throw;
232  }
233  }
234 
235  return *this;
236 }
237 
238 
248 template <class T>
249 inline T* stack<T>::operator[](u32 i) const
250 {
251  return peek(i);
252 }
253 
254 
265 template <class T>
267 {
268  if ( unlikely(d == NULL) )
269  throw exception("invalid argument: d (=%p)", d);
270 
271  /* If the data pointer already exists in the stack */
272  if ( unlikely(node_with(d) != NULL) )
273  throw exception("stack @ %p has a node with data @ %p", this, d);
274 
275  node<T> *n = new node<T>(d);
276  n->m_link = m_top;
277  m_top = n;
278  m_size++;
279 
280  return *this;
281 }
282 
283 
289 template <class T>
291 {
292  __D_ASSERT(m_size > 0);
293  if ( likely(m_size != 0) ) {
294  node<T> *n = m_top;
295  m_top = m_top->m_link;
296  m_size--;
297  delete n;
298  }
299 
300  return *this;
301 }
302 
303 
309 template <class T>
311 {
312  node<T> *n = m_top;
313  while ( likely(n != NULL) ) {
314  node<T> *tmp = n->m_link;
315  delete n;
316  n = tmp;
317  }
318 
319  m_top = NULL;
320  m_size = 0;
321  return *this;
322 }
323 
324 
334 template <class T>
335 inline T* stack<T>::peek(u32 i) const
336 {
337  return node_at(i)->m_data;
338 }
339 
340 
348 template <class T>
349 stack<T>& stack<T>::foreach(void (*pfunc)(u32, T*)) const
350 {
351  __D_ASSERT(pfunc != NULL);
352  if ( unlikely(pfunc == NULL) )
353  return const_cast<stack<T>&> (*this);
354 
355  u32 i = 0;
356  for (node<T> *n = m_top; likely(n != NULL); n = n->m_link)
357  pfunc(i++, n->m_data);
358 
359  return const_cast<stack<T>&> (*this);
360 }
361 
362 }
363 
364 #endif
365 
virtual T * operator[](u32) const
Subscript operator.
Definition: stack.hpp:249
virtual ~stack()
Object destructor.
Definition: stack.hpp:165
virtual stack * clone() const
Object virtual copy constructor.
Definition: stack.hpp:179
This abstract class serves as the root of the class hierarchy tree.
Definition: object.hpp:17
virtual T * peek(u32) const
Get the node data pointer at a stack offset.
Definition: stack.hpp:335
virtual u32 size() const
Get the stack size (node count)
Definition: stack.hpp:191
virtual node< T > * node_at(u32 i) const
Get the node at a stack offset.
Definition: stack.hpp:94
Lightweight, templated, singly-linked LIFO queue (stack)
Definition: stack.hpp:28
#define likely(expr)
Offer a hint (positive) to the pipeline branch predictor.
Definition: config.hpp:344
virtual stack & foreach(void(*)(u32, T *)) const
Traverse the stack with a callback for each node.
Definition: stack.hpp:349
A node in a templated chain (doubly-linked list) or stack (singly-linked LIFO queue) ...
Definition: node.hpp:36
u32 m_size
Node count.
Definition: stack.hpp:36
node< T > * m_top
Stack top.
Definition: stack.hpp:34
Class csdbg::exception definition.
stack()
Object default constructor.
Definition: stack.hpp:133
unsigned int u32
32-bit unsigned integer
Definition: config.hpp:102
Class csdbg::node definition and method implementation.
virtual stack & clear()
Empty the stack.
Definition: stack.hpp:310
This class is a throwable with a textual description of an error.
Definition: exception.hpp:26
virtual stack & push(T *)
Push a node on the stack.
Definition: stack.hpp:266
virtual node< T > * node_with(const T *) const
Get the node with m_data == d.
Definition: stack.hpp:115
#define unlikely(expr)
Offer a hint (negative) to the pipeline branch predictor.
Definition: config.hpp:349
node * m_link
Next node link (direct or XOR link)
Definition: node.hpp:42
virtual stack & operator=(const stack &)
Assignment operator.
Definition: stack.hpp:211
#define __D_ASSERT(x)
Assertion macro.
Definition: config.hpp:268
virtual stack & pop()
Remove the top stack node.
Definition: stack.hpp:290