adevs_bag.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /**
  2. * Copyright (c) 2013, James Nutaro
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. * The views and conclusions contained in the software and documentation are those
  26. * of the authors and should not be interpreted as representing official policies,
  27. * either expressed or implied, of the FreeBSD Project.
  28. *
  29. * Bugs, comments, and questions can be sent to nutaro@gmail.com
  30. */
  31. #ifndef _adevs_bag_h
  32. #define _adevs_bag_h
  33. #include <cstdlib>
  34. namespace adevs
  35. {
  36. /**
  37. * The Bag is (almost) a model of a STL Multiple Associative Container.
  38. * This implementation is optimized for the simulation engine, and it
  39. * does not satisfy the STL complexity requirements. Neither does it implement
  40. * the full set of required methods, but those methods that are implemented
  41. * conform to the standard (except for the time complexity requirement).
  42. */
  43. template <class T> class Bag
  44. {
  45. public:
  46. /// A bidirectional iterator for the Bag
  47. class iterator
  48. {
  49. public:
  50. /// Default constructor
  51. iterator(){}
  52. /// Copy constructor
  53. iterator(const iterator& src):i(src.i),b(src.b){}
  54. /// Copy by assignment
  55. const iterator& operator=(const iterator& src)
  56. {
  57. i = src.i;
  58. b = src.b;
  59. return *this;
  60. }
  61. /// True if two iterators point at the same position in the bag
  62. bool operator==(const iterator& src) const { return i==src.i; }
  63. /// True if two iterators point at different positions in the bag
  64. bool operator!=(const iterator& src) const { return i!=src.i; }
  65. /// Get the element at the current position
  66. T& operator*() { return b[i]; }
  67. /// Get the element at the current position
  68. const T& operator*() const { return b[i]; }
  69. /// Move to the next position and get the element there
  70. iterator& operator++() { i++; return *this; }
  71. /// Move to the next position and get the element there
  72. iterator& operator++(int) { ++i; return *this; }
  73. /// Move to the previous position and get the element there
  74. iterator& operator--() { i--; return *this; }
  75. /// Move to the previous position and get the element there
  76. iterator& operator--(int) { --i; return *this; }
  77. private:
  78. friend class Bag<T>;
  79. unsigned int i;
  80. T* b;
  81. iterator(unsigned int start, T* b):i(start),b(b){}
  82. };
  83. /// A bidirection iterator for the Bag that should not change its contents
  84. typedef iterator const_iterator;
  85. /// Create an empty bag with an initial capacity
  86. Bag(unsigned int cap = 8):
  87. cap_(cap),size_(0),b(new T[cap]){}
  88. /// Copy constructor uses the = operator of T
  89. Bag(const Bag<T>& src):
  90. cap_(src.cap_),
  91. size_(src.size_)
  92. {
  93. b = new T[src.cap_];
  94. for (unsigned int i = 0; i < size_; i++)
  95. b[i] = src.b[i];
  96. }
  97. /// Assignment operator uses the = operator of T
  98. const Bag<T>& operator=(const Bag<T>& src)
  99. {
  100. cap_ = src.cap_;
  101. size_ = src.size_;
  102. delete [] b;
  103. b = new T[src.cap_];
  104. for (unsigned int i = 0; i < size_; i++)
  105. b[i] = src.b[i];
  106. return *this;
  107. }
  108. /// Swaps contents of this bag with the contents of the supplied bag. Returns this bag.
  109. Bag<T>& swap(Bag<T>& src)
  110. {
  111. unsigned tmp_cap_, tmp_size_;
  112. T* tmp_b;
  113. tmp_cap_ = src.cap_;
  114. tmp_size_ = src.size_;
  115. tmp_b = src.b;
  116. src.cap_ = cap_;
  117. src.size_ = size_;
  118. src.b = b;
  119. cap_ = tmp_cap_;
  120. size_ = tmp_size_;
  121. b = tmp_b;
  122. return *this;
  123. }
  124. /// Count the instances of a stored in the bag
  125. unsigned count(const T& a) const
  126. {
  127. unsigned result = 0;
  128. for (unsigned i = 0; i < size_; i++)
  129. if (b[i] == a) result++;
  130. return result;
  131. }
  132. /// Get the number of elements in the bag
  133. unsigned size() const { return size_; }
  134. /// Same as size()==0
  135. bool empty() const { return size_ == 0; }
  136. /// Get an iterator pointing to the first element in the bag
  137. iterator begin() const { return iterator(0,b); }
  138. /// Get an iterator to the end of the bag (i.e., just after the last element)
  139. iterator end() const { return iterator(size_,b); }
  140. /// Erase the first instance of k
  141. void erase(const T& k)
  142. {
  143. iterator p = find(k);
  144. if (p != end()) erase(p);
  145. }
  146. /// Erase the element pointed to by p
  147. void erase(iterator p)
  148. {
  149. size_--;
  150. b[p.i] = b[size_];
  151. }
  152. /// Remove all of the elements from the bag
  153. void clear() { size_ = 0; }
  154. /// Find the first instance of k, or end() if no instance is found. Uses == for comparing T.
  155. iterator find(const T& k) const
  156. {
  157. for (unsigned i = 0; i < size_; i++)
  158. if (b[i] == k) return iterator(i,b);
  159. return end();
  160. }
  161. /// Put t into the bag
  162. void insert(const T& t)
  163. {
  164. if (cap_ == size_) enlarge(2*cap_);
  165. b[size_] = t;
  166. size_++;
  167. }
  168. /// Access the element at position k
  169. const T& operator[](unsigned k) const { return b[k]; }
  170. /// Access the element at position k
  171. T& operator[](unsigned k) { return b[k]; }
  172. /// Delete the bag
  173. ~Bag() { delete [] b; }
  174. private:
  175. unsigned cap_, size_;
  176. T* b;
  177. /// Adds the specified capacity to the bag.
  178. void enlarge(unsigned adjustment)
  179. {
  180. cap_ = cap_ + adjustment;
  181. T* rb = new T[cap_];
  182. for (unsigned i = 0; i < size_; i++)
  183. rb[i] = b[i];
  184. delete [] b;
  185. b = rb;
  186. }
  187. };
  188. } // end of namespace
  189. #endif