circular_queue.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /*************************************************************************************************/ 00008 00009 #ifndef ADOBE_CIRCULAR_QUEUE_HPP 00010 #define ADOBE_CIRCULAR_QUEUE_HPP 00011 00012 /*************************************************************************************************/ 00013 00014 #include <adobe/config.hpp> 00015 00016 #include <adobe/algorithm/equal.hpp> 00017 #include <adobe/iterator.hpp> 00018 #include <adobe/move.hpp> 00019 00020 #include <boost/operators.hpp> 00021 00022 #include <cassert> 00023 #include <vector> 00024 00025 /*************************************************************************************************/ 00026 00027 namespace adobe { 00207 /*************************************************************************************************/ 00208 00209 #if 1 // REVISIT (fbrereto) : Possible compiler optimization? 00210 #define ADOBE_NOTHROW throw() 00211 #else 00212 #define ADOBE_NOTHROW 00213 #endif 00214 00215 /*************************************************************************************************/ 00216 00217 template <typename T> class circular_queue; 00218 00219 template <typename T> 00220 bool operator == (const circular_queue<T>& x, const circular_queue<T>& y); 00221 00222 template <typename T> 00223 void swap(circular_queue<T>&, circular_queue<T>&); 00224 00225 /*************************************************************************************************/ 00226 00243 template <typename T> 00244 class circular_queue : boost::equality_comparable<circular_queue<T> > 00245 { 00246 public: 00247 typedef T value_type; 00248 typedef T* pointer; 00249 typedef const T* const_pointer; 00250 typedef T& reference; 00251 typedef const T& const_reference; 00252 typedef std::size_t size_type; 00253 00254 circular_queue(std::size_t capacity = 0); 00255 00256 #if !defined(ADOBE_NO_DOCUMENTATION) 00257 circular_queue(const circular_queue& rhs); 00258 00259 circular_queue& operator = (circular_queue rhs); 00260 #endif // !defined(ADOBE_NO_DOCUMENTATION) 00261 00262 size_type size() const ADOBE_NOTHROW; 00263 size_type max_size() const ADOBE_NOTHROW { return container_m.size(); } 00264 size_type capacity() const ADOBE_NOTHROW { return container_m.size(); } 00265 00266 bool empty() const ADOBE_NOTHROW { return is_empty_m; } 00267 bool full() const ADOBE_NOTHROW { return !is_empty_m && begin_m == end_m; } 00268 00269 void clear() ADOBE_NOTHROW { begin_m = end_m; is_empty_m = true; } 00270 00271 reference front() ADOBE_NOTHROW; 00272 const_reference front() const ADOBE_NOTHROW; 00273 00274 void push_back(T x); 00275 00276 void pop_front() ADOBE_NOTHROW; 00277 00278 void putback() ADOBE_NOTHROW; 00279 00280 #if !defined(ADOBE_NO_DOCUMENTATION) 00281 private: 00282 friend inline void swap(circular_queue& x, circular_queue& y) 00283 { 00284 swap(x.container_m, y.container_m); 00285 std::swap(x.begin_m, y.begin_m); 00286 std::swap(x.end_m, y.end_m); 00287 swap(x.is_empty_m, y.is_empty_m); 00288 } 00289 00290 friend bool operator == <> (const circular_queue& x, 00291 const circular_queue& y); 00292 00293 typedef typename std::vector<value_type> container_t; 00294 typedef typename container_t::iterator iterator; 00295 typedef typename container_t::const_iterator const_iterator; 00296 00297 /* WARNING (sparent) : Order of members is important to initialization */ 00298 container_t container_m; 00299 iterator begin_m; 00300 iterator end_m; 00301 bool is_empty_m; 00302 /* WARNING (sparent) : Order of members is important to initialization */ 00303 00304 // Note that these ranges assume non-empty. 00305 00306 typedef std::pair<const_iterator, const_iterator> const_range; 00307 00308 const_range first_range() const 00309 { return const_range(begin_m, begin_m < end_m ? const_iterator(end_m) : boost::end(container_m)); } 00310 00311 const_range second_range() const 00312 { return const_range(begin_m < end_m ? const_iterator(end_m) : boost::begin(container_m), end_m); } 00313 00314 #endif // !defined(ADOBE_NO_DOCUMENTATION) 00315 }; 00316 00317 /*************************************************************************************************/ 00318 00319 template <typename T> 00320 circular_queue<T>::circular_queue(std::size_t capacity) : 00321 container_m(capacity), 00322 begin_m(boost::begin(container_m)), 00323 end_m(boost::begin(container_m)), 00324 is_empty_m(true) 00325 { } 00326 00327 #if !defined(ADOBE_NO_DOCUMENTATION) 00328 00329 /*************************************************************************************************/ 00330 00331 template <typename T> 00332 circular_queue<T>::circular_queue(const circular_queue& rhs) : 00333 container_m (rhs.capacity()), 00334 begin_m (boost::begin(container_m)), 00335 end_m (boost::begin(container_m)), 00336 is_empty_m (rhs.is_empty_m) 00337 { 00338 if (is_empty_m) return; 00339 00340 end_m = copy(rhs.first_range(), end_m); 00341 end_m = copy(rhs.second_range(), end_m); 00342 } 00343 00344 /*************************************************************************************************/ 00345 00346 template <typename T> 00347 inline circular_queue<T>& circular_queue<T>::operator = (circular_queue rhs) 00348 { swap(*this, rhs); return *this; } 00349 00350 #endif // !defined(ADOBE_NO_DOCUMENTATION) 00351 /*************************************************************************************************/ 00352 00353 template <typename T> 00354 typename circular_queue<T>::reference circular_queue<T>::front() ADOBE_NOTHROW 00355 { 00356 assert(!empty()); 00357 return *begin_m; 00358 } 00359 00360 /*************************************************************************************************/ 00361 00362 template <typename T> 00363 typename circular_queue<T>::const_reference circular_queue<T>::front() const 00364 ADOBE_NOTHROW 00365 { 00366 assert(!empty()); 00367 return *begin_m; 00368 } 00369 00370 /*************************************************************************************************/ 00371 00372 template <typename T> 00373 void circular_queue<T>::push_back(T x) 00374 { 00375 *end_m = adobe::move(x); 00376 00377 bool was_full (full()); 00378 00379 if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m); 00380 if (was_full) begin_m = end_m; 00381 00382 is_empty_m = false; 00383 } 00384 00385 /*************************************************************************************************/ 00386 00387 template <typename T> 00388 void circular_queue<T>::pop_front() ADOBE_NOTHROW 00389 { 00390 assert(!empty()); 00391 if (++begin_m == boost::end(container_m)) 00392 begin_m = boost::begin(container_m); 00393 is_empty_m = begin_m == end_m; 00394 } 00395 00396 /*************************************************************************************************/ 00397 00398 template <typename T> 00399 void circular_queue<T>::putback() ADOBE_NOTHROW 00400 { 00401 assert(!full()); 00402 if (begin_m == boost::begin(container_m)) 00403 begin_m = boost::end(container_m); 00404 --begin_m; 00405 is_empty_m = false; 00406 } 00407 00408 /*************************************************************************************************/ 00409 00410 template <typename T> 00411 typename circular_queue<T>::size_type circular_queue<T>::size() const ADOBE_NOTHROW 00412 { 00413 if (begin_m < end_m) return std::distance(begin_m, end_m); 00414 00415 return is_empty_m ? 0 : capacity() - std::distance(end_m, begin_m); 00416 } 00417 00418 /*************************************************************************************************/ 00419 00420 template <typename T> 00421 bool operator == ( const circular_queue<T>& x, 00422 const circular_queue<T>& y) 00423 { 00424 /* 00425 REVISIT (sparent) : I'm trying to move the code towards equality of containers to mean "the 00426 size is the same and all the parts are the same." By making the segmented iterators part of 00427 a public begin, end interface this would simply be a generic. "equal_containers()" function. 00428 */ 00429 typedef typename circular_queue<T>::const_range const_range; 00430 00431 if (x.size() != y.size()) return false; 00432 00433 const_range sequence1[] = { x.first_range(), x.second_range() }; 00434 const_range sequence2[] = { y.first_range(), y.second_range() }; 00435 00436 return equal(make_segmented_range(sequence1), 00437 make_segmented_iterator(sequence2)); 00438 } 00439 00440 /*************************************************************************************************/ 00441 00442 #undef ADOBE_NOTHROW 00443 00444 /*************************************************************************************************/ 00445 00446 } // namespace adobe 00447 00448 /*************************************************************************************************/ 00449 00450 #endif // ADOBE_CIRCULAR_QUEUE_HPP 00451 00452 /*************************************************************************************************/ |