Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stack.h
00001 ///\file 00002 00003 /****************************************************************************** 00004 The MIT License(MIT) 00005 00006 Embedded Template Library. 00007 https://github.com/ETLCPP/etl 00008 http://www.etlcpp.com 00009 00010 Copyright(c) 2014 jwellbelove, Mark Kitson 00011 00012 Permission is hereby granted, free of charge, to any person obtaining a copy 00013 of this software and associated documentation files(the "Software"), to deal 00014 in the Software without restriction, including without limitation the rights 00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00016 copies of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions : 00018 00019 The above copyright notice and this permission notice shall be included in all 00020 copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00028 SOFTWARE. 00029 ******************************************************************************/ 00030 00031 #ifndef __ETL_STACK__ 00032 #define __ETL_STACK__ 00033 00034 #include <stddef.h> 00035 #include <stdint.h> 00036 #include <algorithm> 00037 00038 #include "platform.h " 00039 #include "container.h " 00040 #include "alignment.h " 00041 #include "array.h " 00042 #include "exception.h " 00043 #include "error_handler.h " 00044 #include "debug_count.h " 00045 #include "type_traits.h " 00046 #include "parameter_type.h " 00047 00048 #define ETL_FILE "15" 00049 00050 //***************************************************************************** 00051 ///\defgroup stack stack 00052 /// A Last-in / first-out stack with the capacity defined at compile time, 00053 /// written in the STL style. 00054 ///\ingroup containers 00055 //***************************************************************************** 00056 00057 namespace etl 00058 { 00059 //*************************************************************************** 00060 ///\ingroup stack 00061 /// The base class for stack exceptions. 00062 //*************************************************************************** 00063 class stack_exception : public exception 00064 { 00065 public: 00066 00067 stack_exception(string_type reason_, string_type file_name_, numeric_type line_number_) 00068 : exception(reason_, file_name_, line_number_) 00069 { 00070 } 00071 }; 00072 00073 //*************************************************************************** 00074 ///\ingroup stack 00075 /// The exception thrown when the stack is full. 00076 //*************************************************************************** 00077 class stack_full : public stack_exception 00078 { 00079 public: 00080 00081 stack_full(string_type file_name_, numeric_type line_number_) 00082 : stack_exception(ETL_ERROR_TEXT("stack:full", ETL_FILE"A"), file_name_, line_number_) 00083 { 00084 } 00085 }; 00086 00087 //*************************************************************************** 00088 ///\ingroup stack 00089 /// The exception thrown when the stack is empty. 00090 //*************************************************************************** 00091 class stack_empty : public stack_exception 00092 { 00093 public: 00094 00095 stack_empty(string_type file_name_, numeric_type line_number_) 00096 : stack_exception(ETL_ERROR_TEXT("stack:empty", ETL_FILE"B"), file_name_, line_number_) 00097 { 00098 } 00099 }; 00100 00101 //*************************************************************************** 00102 ///\ingroup stack 00103 /// A fixed capacity stack written in the STL style. 00104 /// \warntopg This stack cannot be used for concurrent access from multiple threads. 00105 //*************************************************************************** 00106 class stack_base 00107 { 00108 public: 00109 00110 typedef size_t size_type; ///< The type used for determining the size of stack. 00111 00112 //************************************************************************* 00113 /// Checks to see if the stack is empty. 00114 /// \return <b>true</b> if the stack is empty, otherwise <b>false</b> 00115 //************************************************************************* 00116 bool empty() const 00117 { 00118 return current_size == 0; 00119 } 00120 00121 //************************************************************************* 00122 /// Checks to see if the stack is full. 00123 /// \return <b>true</b> if the stack is full, otherwise <b>false</b> 00124 //************************************************************************* 00125 bool full() const 00126 { 00127 return current_size == CAPACITY; 00128 } 00129 00130 //************************************************************************* 00131 /// Returns the current number of items top the stack. 00132 //************************************************************************* 00133 size_type size() const 00134 { 00135 return current_size; 00136 } 00137 00138 //************************************************************************* 00139 /// Returns the maximum number of items that can be stacked. 00140 //************************************************************************* 00141 size_type max_size() const 00142 { 00143 return CAPACITY; 00144 } 00145 00146 //************************************************************************* 00147 /// Returns the remaining capacity. 00148 ///\return The remaining capacity. 00149 //************************************************************************* 00150 size_t available() const 00151 { 00152 return max_size() - size(); 00153 } 00154 00155 protected: 00156 00157 //************************************************************************* 00158 /// The constructor that is called from derived classes. 00159 //************************************************************************* 00160 stack_base(size_type max_size_) 00161 : top_index(0), 00162 current_size(0), 00163 CAPACITY(max_size_) 00164 { 00165 } 00166 00167 //************************************************************************* 00168 /// Increments the indexes value to record a stack addition. 00169 //************************************************************************* 00170 void add_in() 00171 { 00172 top_index = current_size++; 00173 ++construct_count; 00174 } 00175 00176 //************************************************************************* 00177 /// Decrements the indexes value to record a queue deletion. 00178 //************************************************************************* 00179 void del_out() 00180 { 00181 --top_index; 00182 --current_size; 00183 --construct_count; 00184 } 00185 00186 size_type top_index; ///< The index of the top of the stack. 00187 size_type current_size; ///< The number of items in the stack. 00188 const size_type CAPACITY; ///< The maximum number of items in the stack. 00189 etl::debug_count construct_count; ///< For internal debugging purposes. 00190 }; 00191 00192 //*************************************************************************** 00193 ///\ingroup stack 00194 ///\brief This is the base for all stacks that contain a particular type. 00195 ///\details Normally a reference to this type will be taken from a derived stack. 00196 ///\code 00197 /// etl::stack<int, 10> myStack; 00198 /// etl::istack<int>& iStack = myStack; 00199 ///\endcode 00200 /// \warning This stack cannot be used for concurrent access from multiple threads. 00201 /// \tparam T The type of value that the stack holds. 00202 //*************************************************************************** 00203 template <typename T> 00204 class istack : public etl::stack_base 00205 { 00206 public: 00207 00208 typedef T value_type; ///< The type stored in the stack. 00209 typedef T& reference; ///< A reference to the type used in the stack. 00210 typedef const T& const_reference; ///< A const reference to the type used in the stack. 00211 typedef T* pointer; ///< A pointer to the type used in the stack. 00212 typedef const T* const_pointer; ///< A const pointer to the type used in the stack. 00213 typedef stack_base::size_type size_type; ///< The type used for determining the size of the stack. 00214 00215 private: 00216 00217 typedef typename etl::parameter_type<T>::type parameter_t; 00218 typedef typename etl::stack_base base_t; 00219 00220 public: 00221 00222 //************************************************************************* 00223 /// Gets a reference to the value at the top of the stack.<br> 00224 /// \return A reference to the value at the top of the stack. 00225 //************************************************************************* 00226 reference top() 00227 { 00228 return p_buffer[top_index]; 00229 } 00230 00231 //************************************************************************* 00232 /// Adds a value to the stack. 00233 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00234 ///\param value The value to push to the stack. 00235 //************************************************************************* 00236 void push(parameter_t value) 00237 { 00238 #if defined(ETL_CHECK_PUSH_POP) 00239 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00240 #endif 00241 base_t::add_in(); 00242 ::new (&p_buffer[top_index]) T(value); 00243 } 00244 00245 //************************************************************************* 00246 /// Constructs a value in the stack place'. 00247 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00248 ///\param value The value to push to the stack. 00249 //************************************************************************* 00250 template <typename T1> 00251 void emplace(const T1& value1) 00252 { 00253 #if defined(ETL_CHECK_PUSH_POP) 00254 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00255 #endif 00256 base_t::add_in(); 00257 ::new (&p_buffer[top_index]) T(value1); 00258 } 00259 00260 //************************************************************************* 00261 /// Constructs a value in the stack place'. 00262 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00263 ///\param value The value to push to the stack. 00264 //************************************************************************* 00265 template <typename T1, typename T2> 00266 void emplace(const T1& value1, const T2& value2) 00267 { 00268 #if defined(ETL_CHECK_PUSH_POP) 00269 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00270 #endif 00271 base_t::add_in(); 00272 ::new (&p_buffer[top_index]) T(value1, value2); 00273 } 00274 00275 //************************************************************************* 00276 /// Constructs a value in the stack place'. 00277 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00278 ///\param value The value to push to the stack. 00279 //************************************************************************* 00280 template <typename T1, typename T2, typename T3> 00281 void emplace(const T1& value1, const T2& value2, const T3& value3) 00282 { 00283 #if defined(ETL_CHECK_PUSH_POP) 00284 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00285 #endif 00286 base_t::add_in(); 00287 ::new (&p_buffer[top_index]) T(value1, value2, value3); 00288 } 00289 00290 //************************************************************************* 00291 /// Constructs a value in the stack place'. 00292 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00293 ///\param value The value to push to the stack. 00294 //************************************************************************* 00295 template <typename T1, typename T2, typename T3, typename T4> 00296 void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) 00297 { 00298 #if defined(ETL_CHECK_PUSH_POP) 00299 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00300 #endif 00301 base_t::add_in(); 00302 ::new (&p_buffer[top_index]) T(value1, value2, value3, value4); 00303 } 00304 00305 //************************************************************************* 00306 /// Allows a possibly more efficient 'push' by moving to the next input value 00307 /// and returning a reference to it. 00308 /// This may eliminate a copy by allowing direct construction in-place.<br> 00309 /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. 00310 /// \return A reference to the position to 'push' to. 00311 //************************************************************************* 00312 reference push() 00313 { 00314 #if defined(ETL_CHECK_PUSH_POP) 00315 ETL_ASSERT(!full(), ETL_ERROR(stack_full)); 00316 #endif 00317 base_t::add_in(); 00318 00319 return p_buffer[top_index]; 00320 } 00321 00322 //************************************************************************* 00323 /// Gets a const reference to the value at the top of the stack.<br> 00324 /// \return A const reference to the value at the top of the stack. 00325 //************************************************************************* 00326 const_reference top() const 00327 { 00328 return p_buffer[top_index]; 00329 } 00330 00331 //************************************************************************* 00332 /// Clears the stack to the empty state. 00333 //************************************************************************* 00334 void clear() 00335 { 00336 while (current_size > 0) 00337 { 00338 p_buffer[top_index].~T(); 00339 base_t::del_out(); 00340 } 00341 } 00342 00343 //************************************************************************* 00344 /// Removes the oldest item from the top of the stack. 00345 //************************************************************************* 00346 void pop() 00347 { 00348 #if defined(ETL_CHECK_PUSH_POP) 00349 ETL_ASSERT(!empty(), ETL_ERROR(stack_empty)); 00350 #endif 00351 p_buffer[top_index].~T(); 00352 base_t::del_out(); 00353 } 00354 00355 //************************************************************************* 00356 /// Removes the oldest item from the top of the stack and puts it in the destination. 00357 //************************************************************************* 00358 void pop_into(reference destination) 00359 { 00360 destination = top(); 00361 pop(); 00362 } 00363 00364 //************************************************************************* 00365 /// Removes the oldest item from the top of the stack and pushes it to the 00366 /// destination container. 00367 /// NOTE: The destination must support a push(T) member function. 00368 //************************************************************************* 00369 template <typename TContainer> 00370 void pop_into(TContainer& destination) 00371 { 00372 destination.push(top()); 00373 pop(); 00374 } 00375 00376 //************************************************************************* 00377 /// Reverses the stack. 00378 //************************************************************************* 00379 void reverse() 00380 { 00381 std::reverse(p_buffer, p_buffer + current_size); 00382 } 00383 00384 //************************************************************************* 00385 /// Assignment operator. 00386 //************************************************************************* 00387 istack& operator = (const istack& rhs) 00388 { 00389 if (&rhs != this) 00390 { 00391 clear(); 00392 clone(rhs); 00393 } 00394 00395 return *this; 00396 } 00397 00398 protected: 00399 00400 //************************************************************************* 00401 /// Make this a clone of the supplied stack 00402 //************************************************************************* 00403 void clone(const istack& other) 00404 { 00405 size_t index = 0; 00406 00407 for (size_t i = 0; i < other.size(); ++i) 00408 { 00409 push(other.p_buffer[index++]); 00410 } 00411 } 00412 00413 //************************************************************************* 00414 /// The constructor that is called from derived classes. 00415 //************************************************************************* 00416 istack(T* p_buffer_, size_type max_size_) 00417 : stack_base(max_size_), 00418 p_buffer(p_buffer_) 00419 { 00420 } 00421 00422 private: 00423 00424 // Disable copy construction. 00425 istack(const istack&); 00426 00427 T* p_buffer; ///< The internal buffer. 00428 }; 00429 00430 //*************************************************************************** 00431 ///\ingroup stack 00432 /// A fixed capacity stack. 00433 /// This stack does not suppo7rt concurrent access by different threads. 00434 /// \tparam T The type this stack should support. 00435 /// \tparam MAX_SIZE The maximum capacity of the stack. 00436 //*************************************************************************** 00437 template <typename T, const size_t SIZE> 00438 class stack : public etl::istack<T> 00439 { 00440 public: 00441 00442 static const size_t MAX_SIZE = SIZE; 00443 00444 //************************************************************************* 00445 /// Default constructor. 00446 //************************************************************************* 00447 stack() 00448 : etl::istack<T>(reinterpret_cast<T*>(&buffer[0]), SIZE) 00449 { 00450 } 00451 00452 //************************************************************************* 00453 /// Copy constructor 00454 //************************************************************************* 00455 stack(const stack& rhs) 00456 : etl::istack<T>(reinterpret_cast<T*>(&buffer[0]), SIZE) 00457 { 00458 etl::istack<T>::clone(rhs); 00459 } 00460 00461 //************************************************************************* 00462 /// Destructor. 00463 //************************************************************************* 00464 ~stack() 00465 { 00466 etl::istack<T>::clear(); 00467 } 00468 00469 //************************************************************************* 00470 /// Assignment operator. 00471 //************************************************************************* 00472 stack& operator = (const stack& rhs) 00473 { 00474 if (&rhs != this) 00475 { 00476 etl::istack<T>::clone(rhs); 00477 } 00478 00479 return *this; 00480 } 00481 00482 private: 00483 00484 /// The unintitialised buffer of T used in the stack. 00485 typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[SIZE]; 00486 }; 00487 } 00488 00489 #undef ETL_FILE 00490 00491 #endif 00492
Generated on Tue Jul 12 2022 14:05:44 by
