Embedded Template Library  1.0
stack.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2014 jwellbelove, Mark Kitson
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_STACK_INCLUDED
32 #define ETL_STACK_INCLUDED
33 
34 #include <stddef.h>
35 #include <stdint.h>
36 
37 #include "platform.h"
38 #include "algorithm.h"
39 #include "utility.h"
40 #include "container.h"
41 #include "alignment.h"
42 #include "array.h"
43 #include "exception.h"
44 #include "error_handler.h"
45 #include "debug_count.h"
46 #include "type_traits.h"
47 #include "placement_new.h"
48 
49 #undef ETL_FILE
50 #define ETL_FILE "15"
51 
52 //*****************************************************************************
57 //*****************************************************************************
58 
59 namespace etl
60 {
61  //***************************************************************************
64  //***************************************************************************
65  class stack_exception : public exception
66  {
67  public:
68 
69  stack_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
70  : exception(reason_, file_name_, line_number_)
71  {
72  }
73  };
74 
75  //***************************************************************************
78  //***************************************************************************
79  class stack_full : public stack_exception
80  {
81  public:
82 
83  stack_full(string_type file_name_, numeric_type line_number_)
84  : stack_exception(ETL_ERROR_TEXT("stack:full", ETL_FILE"A"), file_name_, line_number_)
85  {
86  }
87  };
88 
89  //***************************************************************************
92  //***************************************************************************
94  {
95  public:
96 
97  stack_empty(string_type file_name_, numeric_type line_number_)
98  : stack_exception(ETL_ERROR_TEXT("stack:empty", ETL_FILE"B"), file_name_, line_number_)
99  {
100  }
101  };
102 
103  //***************************************************************************
107  //***************************************************************************
109  {
110  public:
111 
112  typedef size_t size_type;
113 
114  //*************************************************************************
117  //*************************************************************************
118  bool empty() const
119  {
120  return current_size == 0;
121  }
122 
123  //*************************************************************************
126  //*************************************************************************
127  bool full() const
128  {
129  return current_size == CAPACITY;
130  }
131 
132  //*************************************************************************
134  //*************************************************************************
135  size_type size() const
136  {
137  return current_size;
138  }
139 
140  //*************************************************************************
142  //*************************************************************************
144  {
145  return CAPACITY;
146  }
147 
148  //*************************************************************************
151  //*************************************************************************
152  size_t available() const
153  {
154  return max_size() - size();
155  }
156 
157  protected:
158 
159  //*************************************************************************
161  //*************************************************************************
163  : top_index(0),
164  current_size(0),
165  CAPACITY(max_size_)
166  {
167  }
168 
169  //*************************************************************************
171  //*************************************************************************
173  {
174  }
175 
176  //*************************************************************************
178  //*************************************************************************
179  void add_in()
180  {
182  ETL_INCREMENT_DEBUG_COUNT
183  }
184 
185  //*************************************************************************
187  //*************************************************************************
188  void del_out()
189  {
190  --top_index;
191  --current_size;
192  ETL_DECREMENT_DEBUG_COUNT
193  }
194 
195  //*************************************************************************
197  //*************************************************************************
198  void index_clear()
199  {
200  top_index = 0;
201  current_size = 0;
202  ETL_RESET_DEBUG_COUNT
203  }
204 
208  ETL_DECLARE_DEBUG_COUNT
209  };
210 
211  //***************************************************************************
221  //***************************************************************************
222  template <typename T>
223  class istack : public etl::stack_base
224  {
225  public:
226 
227  typedef T value_type;
228  typedef T& reference;
229  typedef const T& const_reference;
230 #if ETL_CPP11_SUPPORTED
231  typedef T&& rvalue_reference;
232 #endif
233  typedef T* pointer;
234  typedef const T* const_pointer;
236 
237  private:
238 
239  typedef typename etl::stack_base base_t;
240 
241  public:
242 
243  //*************************************************************************
246  //*************************************************************************
248  {
249  return p_buffer[top_index];
250  }
251 
252  //*************************************************************************
256  //*************************************************************************
257  void push(const_reference value)
258  {
259 #if defined(ETL_CHECK_PUSH_POP)
260  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
261 #endif
262  base_t::add_in();
263  ::new (&p_buffer[top_index]) T(value);
264  }
265 
266 #if ETL_CPP11_SUPPORTED
267  //*************************************************************************
271  //*************************************************************************
272  void push(rvalue_reference value)
273  {
274 #if defined(ETL_CHECK_PUSH_POP)
275  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
276 #endif
277  base_t::add_in();
278  ::new (&p_buffer[top_index]) T(etl::move(value));
279  }
280 #endif
281 
282 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT
283  //*************************************************************************
287  //*************************************************************************
288  template <typename ... Args>
289  void emplace(Args && ... args)
290  {
291 #if defined(ETL_CHECK_PUSH_POP)
292  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
293 #endif
294  base_t::add_in();
295  ::new (&p_buffer[top_index]) T(etl::forward<Args>(args)...);
296  }
297 #else
298  //*************************************************************************
302  //*************************************************************************
303  template <typename T1>
304  void emplace(const T1& value1)
305  {
306 #if defined(ETL_CHECK_PUSH_POP)
307  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
308 #endif
309  base_t::add_in();
310  ::new (&p_buffer[top_index]) T(value1);
311  }
312 
313  //*************************************************************************
317  //*************************************************************************
318  template <typename T1, typename T2>
319  void emplace(const T1& value1, const T2& value2)
320  {
321 #if defined(ETL_CHECK_PUSH_POP)
322  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
323 #endif
324  base_t::add_in();
325  ::new (&p_buffer[top_index]) T(value1, value2);
326  }
327 
328  //*************************************************************************
332  //*************************************************************************
333  template <typename T1, typename T2, typename T3>
334  void emplace(const T1& value1, const T2& value2, const T3& value3)
335  {
336 #if defined(ETL_CHECK_PUSH_POP)
337  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
338 #endif
339  base_t::add_in();
340  ::new (&p_buffer[top_index]) T(value1, value2, value3);
341  }
342 
343  //*************************************************************************
347  //*************************************************************************
348  template <typename T1, typename T2, typename T3, typename T4>
349  void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
350  {
351 #if defined(ETL_CHECK_PUSH_POP)
352  ETL_ASSERT(!full(), ETL_ERROR(stack_full));
353 #endif
354  base_t::add_in();
355  ::new (&p_buffer[top_index]) T(value1, value2, value3, value4);
356  }
357 #endif
358 
359  //*************************************************************************
362  //*************************************************************************
364  {
365  return p_buffer[top_index];
366  }
367 
368  //*************************************************************************
370  //*************************************************************************
371  void clear()
372  {
373  if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
374  {
376  }
377  else
378  {
379  while (current_size > 0)
380  {
381  p_buffer[top_index].~T();
382  base_t::del_out();
383  }
384  }
385  }
386 
387  //*************************************************************************
389  //*************************************************************************
390  void pop()
391  {
392 #if defined(ETL_CHECK_PUSH_POP)
393  ETL_ASSERT(!empty(), ETL_ERROR(stack_empty));
394 #endif
395  p_buffer[top_index].~T();
396  base_t::del_out();
397  }
398 
399  //*************************************************************************
401  //*************************************************************************
402  void pop_into(reference destination)
403  {
404  destination = top();
405  pop();
406  }
407 
408  //*************************************************************************
412  //*************************************************************************
413  template <typename TContainer>
414  void pop_into(TContainer& destination)
415  {
416  destination.push(top());
417  pop();
418  }
419 
420  //*************************************************************************
422  //*************************************************************************
423  void reverse()
424  {
425  etl::reverse(p_buffer, p_buffer + current_size);
426  }
427 
428  //*************************************************************************
430  //*************************************************************************
431  istack& operator = (const istack& rhs)
432  {
433  if (&rhs != this)
434  {
435  clear();
436  clone(rhs);
437  }
438 
439  return *this;
440  }
441 
442 #if ETL_CPP11_SUPPORTED
443  //*************************************************************************
445  //*************************************************************************
446  istack& operator = (istack&& rhs)
447  {
448  if (&rhs != this)
449  {
450  clone(etl::move(rhs));
451  }
452 
453  return *this;
454  }
455 #endif
456 
457  protected:
458 
459  //*************************************************************************
461  //*************************************************************************
462  void clone(const istack& other)
463  {
464  clear();
465 
466  size_t index = 0;
467 
468  for (size_t i = 0; i < other.size(); ++i)
469  {
470  push(other.p_buffer[index++]);
471  }
472  }
473 
474 #if ETL_CPP11_SUPPORTED
475  //*************************************************************************
477  //*************************************************************************
478  void clone(istack&& other)
479  {
480  clear();
481 
482  size_t index = 0;
483 
484  for (size_t i = 0; i < other.size(); ++i)
485  {
486  push(etl::move(other.p_buffer[index++]));
487  }
488  }
489 #endif
490 
491  //*************************************************************************
493  //*************************************************************************
494  istack(T* p_buffer_, size_type max_size_)
495  : stack_base(max_size_),
496  p_buffer(p_buffer_)
497  {
498  }
499 
500  private:
501 
502  // Disable copy construction.
503  istack(const istack&);
504 
505  T* p_buffer;
506 
507  //*************************************************************************
509  //*************************************************************************
510 #if defined(ETL_POLYMORPHIC_STACK) || defined(ETL_POLYMORPHIC_CONTAINERS)
511  public:
512  virtual ~istack()
513  {
514  }
515 #else
516  protected:
518  {
519  }
520 #endif
521  };
522 
523  //***************************************************************************
529  //***************************************************************************
530  template <typename T, const size_t SIZE>
531  class stack : public etl::istack<T>
532  {
533  public:
534 
535  static const size_t MAX_SIZE = SIZE;
536 
537  //*************************************************************************
539  //*************************************************************************
541  : etl::istack<T>(reinterpret_cast<T*>(&buffer[0]), SIZE)
542  {
543  }
544 
545  //*************************************************************************
547  //*************************************************************************
548  stack(const stack& rhs)
549  : etl::istack<T>(reinterpret_cast<T*>(&buffer[0]), SIZE)
550  {
552  }
553 
554 #if ETL_CPP11_SUPPORTED
555  //*************************************************************************
557  //*************************************************************************
558  stack(stack&& rhs)
559  : etl::istack<T>(reinterpret_cast<T*>(&buffer[0]), SIZE)
560  {
561  etl::istack<T>::clone(etl::move(rhs));
562  }
563 #endif
564 
565  //*************************************************************************
567  //*************************************************************************
569  {
571  }
572 
573  //*************************************************************************
575  //*************************************************************************
576  stack& operator = (const stack& rhs)
577  {
578  if (&rhs != this)
579  {
581  }
582 
583  return *this;
584  }
585 
586 #if ETL_CPP11_SUPPORTED
587  //*************************************************************************
589  //*************************************************************************
590  stack& operator = (stack&& rhs)
591  {
592  if (&rhs != this)
593  {
594  etl::istack<T>::clone(etl::move(rhs));
595  }
596 
597  return *this;
598  }
599 #endif
600 
601  private:
602 
604  typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[SIZE];
605  };
606 }
607 
608 #undef ETL_FILE
609 
610 #endif
Definition: alignment.h:116
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
exception(string_type reason_, string_type file_, numeric_type line_)
Constructor.
Definition: exception.h:67
Definition: exception.h:47
void del_out()
Decrements the indexes value to record a queue deletion.
Definition: stack.h:188
reference top()
Definition: stack.h:247
bool empty() const
Definition: stack.h:118
~stack_base()
Destructor.
Definition: stack.h:172
stack()
Default constructor.
Definition: stack.h:540
stack_base(size_type max_size_)
The constructor that is called from derived classes.
Definition: stack.h:162
bool full() const
Definition: stack.h:127
const T * const_pointer
A const pointer to the type used in the stack.
Definition: stack.h:234
const size_type CAPACITY
The maximum number of items in the stack.
Definition: stack.h:207
void emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: stack.h:349
void index_clear()
Clears all of the indexes.
Definition: stack.h:198
size_type size() const
Returns the current number of items top the stack.
Definition: stack.h:135
istack(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition: stack.h:494
size_type max_size() const
Returns the maximum number of items that can be stacked.
Definition: stack.h:143
size_type current_size
The number of items in the stack.
Definition: stack.h:206
void emplace(const T1 &value1)
Definition: stack.h:304
void emplace(const T1 &value1, const T2 &value2)
Definition: stack.h:319
size_t available() const
Definition: stack.h:152
void push(const_reference value)
Definition: stack.h:257
void pop()
Removes the oldest item from the top of the stack.
Definition: stack.h:390
size_type top_index
The index of the top of the stack.
Definition: stack.h:205
size_t size_type
The type used for determining the size of stack.
Definition: stack.h:112
stack & operator=(const stack &rhs)
Assignment operator.
Definition: stack.h:576
istack & operator=(const istack &rhs)
Assignment operator.
Definition: stack.h:431
T & reference
A reference to the type used in the stack.
Definition: stack.h:228
void emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition: stack.h:334
T * pointer
A pointer to the type used in the stack.
Definition: stack.h:233
~stack()
Destructor.
Definition: stack.h:568
stack(const stack &rhs)
Copy constructor.
Definition: stack.h:548
void pop_into(TContainer &destination)
Definition: stack.h:414
void clone(const istack &other)
Make this a clone of the supplied stack.
Definition: stack.h:462
~istack()
Destructor.
Definition: stack.h:517
void pop_into(reference destination)
Removes the oldest item from the top of the stack and puts it in the destination.
Definition: stack.h:402
const T & const_reference
A const reference to the type used in the stack.
Definition: stack.h:229
void add_in()
Increments the indexes value to record a stack addition.
Definition: stack.h:179
void clear()
Clears the stack to the empty state.
Definition: stack.h:371
stack_base::size_type size_type
The type used for determining the size of the stack.
Definition: stack.h:235
T value_type
The type stored in the stack.
Definition: stack.h:227
void reverse()
Reverses the stack.
Definition: stack.h:423
const_reference top() const
Definition: stack.h:363
This is the base for all stacks that contain a particular type.
Definition: stack.h:224
Definition: stack.h:532
Definition: stack.h:109
Definition: stack.h:94
Definition: stack.h:66
Definition: stack.h:80
add_rvalue_reference
Definition: type_traits_generator.h:1348
is_trivially_destructible
Definition: type_traits_generator.h:1171
Definition: absolute.h:37