diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..8c7b08d --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,208 @@ +# Doxyfile 1.3.5 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "Circular Buffer" +PROJECT_NUMBER = 3.6 +OUTPUT_DIRECTORY = srcdoc +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = YES +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = YES +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../../boost/circular_buffer/ +FILE_PATTERNS = *.hpp +RECURSIVE = NO +EXCLUDE = ../../../boost/circular_buffer/debug.hpp \ + ../../../boost/circular_buffer/details.hpp +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_FILE_EXTENSION = .html +HTML_HEADER = header.html +HTML_FOOTER = footer.html +HTML_STYLESHEET = stylesheet.css +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = NO +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = circular_buffer.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/circular_buffer.html b/doc/circular_buffer.html new file mode 100644 index 0000000..e74a9d5 --- /dev/null +++ b/doc/circular_buffer.html @@ -0,0 +1,823 @@ + + + + Templated Circular Buffer Container + + + + + + + + +
+

Templated Circular Buffer Container

+

circular_buffer<T, Alloc>

+
+

Contents

+

   Synopsis
+    Rationale
+    Simple Example
+    Definition
+    Template Parameters
+    Members
+    Friend Functions
+    Model of
+    Type Requirements
+    Semantics
+    Caveats
+    Debug Support
+    Example
+    Notes
+    See also
+    Acknowledgments +

+
+ + + + + + + +
+ + + + + +
Figure:The circular buffer (for someone known as ring or cyclic buffer).
+
+

Synopsis

+

The circular_buffer container provides fixed capacity storage with + constant time insertion and removal of elements at each end of a circular + buffer. When the capacity of the circular_buffer is exhausted, + inserted elements will cause elements at the opposite end to be overwritten. + (See the Figure.) The circular_buffer only allocates memory when + created, when the capacity is adjusted explicitly, or as necessary to + accommodate a resizing or assign operation. (There is also a circular_buffer_space_optimized + available. It is an adaptor of the circular_buffer + which does not allocate memory at once when created rather it allocates memory as needed.) +


+

Rationale

+

A contiguous region of memory utilized as a circular buffer has several unique + and useful characteristics: +

+
    +
  1. + Fixed memory use and no implicit or unexpected memory allocation. +
  2. + Fast constant-time insertion and removal of elements from the front and back. +
  3. + Fast constant-time random access of elements. +
  4. + Suitability for real-time and performance critical applications. +
  5. +
+

The circular_buffer container provides a similar interface to std::vector, + std::deque and std::list including push, + pop, insert, erase, iterators and + compatibility with std algorithms. +

+

Possible applications of the circular_buffer include: +

+ +

The design of the circular_buffer container is guided by the + following principles: +

+
    +
  1. + Maximum efficiency + for envisaged applications. +
  2. + Suitable for general purpose + use. +
  3. + Interoperable with other std + containers and algorithms. +
  4. + The behaviour of the buffer as intuitive + as possible. +
  5. + Suitable for specialization by means of adaptors. (The circular_buffer_space_optimized + is such an example of the adaptor.) +
  6. + Guarantee of basic exception safety.
+
+

Simple Example

+

A brief example using the circular_buffer: +

+
   #include <boost/circular_buffer.hpp>
+
+   int main(int argc, char* argv[]) {
+
+      // Create a circular buffer with capacity for 3 integers.
+      boost::circular_buffer<int> cb(3);
+
+      cb.push_back(1);  // Insert the first element.
+      cb.push_back(2);  // Insert the second element.
+      cb.push_back(3);  // Insert the third element.
+
+      // The buffer is full now, pushing subsequent
+      // elements will overwrite the front-most elements.
+      
+      cb.push_back(4);  // Overwrite 1 with 4.
+      cb.push_back(5);  // Overwrite 2 with 5.
+
+      // The buffer now contains 3, 4 and 5.
+      int a = cb[0];  // a == 3
+      int b = cb[1];  // b == 4
+      int c = cb[2];  // c == 5
+
+      // Elements can be popped from either the front or back.
+
+      cb.pop_back();  // 5 is removed.
+      cb.pop_front(); // 3 is removed.
+
+      int d = cb[0];  // d == 4
+
+      return 0;
+   }
+
+
+

Definition

+

#include <boost/circular_buffer.hpp> +

+

+ In fact the circular_buffer is defined in the file + boost/circular_buffer/base.hpp, but it is necessary to + include the boost/circular_buffer.hpp + in order to use this container. Also, there is a forward declaration for circular_buffer + in the header boost/circular_buffer_fwd.hpp. +

+
+

Template Parameters

+ + + + + + + + + + + + + + + +
+ Parameter + Description + Default
TThe type of the elements stored in the circular buffer. 
AllocThe allocator type used for all internal memory management.std::allocator
+
+
+

Members

+

Refer the source code documentation for a + detailed description.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Type + Description
value_type + The type of the elements stored in the circular buffer. +
allocator_typeThe type of the allocator used in the circular buffer.
iterator + Iterator (random access) used to iterate through a circular buffer. +
pointer + Pointer to the element. +
reference + Reference to the element. +
reverse_iterator + Iterator used to iterate backwards through a circular buffer. +
const_iterator + Const (random access) iterator used to iterate through a circular buffer. +
const_pointer + Const pointer to the element. +
const_reference + Const reference to the element. +
const_reverse_iterator + Const iterator used to iterate backwards through a circular buffer. +
difference_type + Distance type. A signed integral type used to represent the distance between + two iterators. +
size_type + Size type. An unsigned integral type that can represent any nonnegative value + of the container's distance type. +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Method + + Description +
circular_buffer(size_type + capacity, const allocator_type& alloc = allocator_type()) + Create an empty circular buffer with a given capacity. +
circular_buffer(size_type + capacity, const T& item, const allocator_type& alloc = + allocator_type()) + Create a full circular buffer with a given capacity and filled with copies of + item. +
circular_buffer(const + circular_buffer& cb) + Copy constructor. +
template<InputIterator> + circular_buffer(size_type capacity, InputIterator first, InputIterator + last, const allocator_type& alloc = allocator_type()) + Create a circular buffer with a copy of a range. +
~circular_buffer() + Destructor. +
template<InputIterator> + assign(InputIterator first, InputIterator last) + Assign a copy of range. +
assign(size_type + n, const T& item) + Assign n items into the circular buffer. +
push_back() + Insert a new element with the default value at the end. +
push_back(const + T& item) + Insert a new element at the end. +
push_front() + Inserts a new element with the default value at the start. +
push_front(const + T& item) + Insert a new element at the start. +
pop_back() + Remove the last (rightmost) element. +
pop_front() + Remove the first (left-most) element. +
front()* + Return the first (leftmost) element. +
back()* + Return the last (rightmost) element. +
at(size_type + index)* + Return the element at the index position. +
operator[](size_type + index)* + Return the element at the index position. +
data() + Return pointer to data stored in the circular buffer as a continuous array of + values. +
insert(iterator + pos) + Insert a new element with the default value before the given position. +
insert(iterator + pos, const T& item) + Insert the item before the given position. +
insert(iterator + pos, size_type n, const T& item) + Insert n copies of the item before the given + position. +
template<InputIterator> + insert(iterator pos, InputIterator first, InputIterator last) + Insert the range [first, last) before the given position. +
rinsert(iterator + pos) + Insert a new element with the default value before the given position. +
rinsert(iterator + pos, const T& item) + Insert the item before the given position. +
rinsert(iterator + pos, size_type n, const T& item) + Insert n copies of the item before the given + position. +
template<InputIterator> + rinsert(iterator pos, InputIterator first, InputIterator last) + Insert the range [first, last) before the given position. +
erase(iterator + pos) + Erase the element at the given position. +
erase(iterator + first, iterator last) + Erase the range [first, last). +
clear() + Erase all the stored elements. +
empty() const + Is the circular buffer empty? +
full() const + Is the circular buffer full? +
size() const + Return the number of elements currently stored in the circular buffer. +
resize(size_type + new_size, param_value_type item = T(), bool remove_front = true) + Change the size of the circular buffer. +
max_size() const + Return the largest possible size (or capacity) of the circular buffer. +
capacity() const + Return the capacity of the circular buffer. +
set_capacity(size_type + new_capacity, bool remove_front = true) + Change the capacity of the circular buffer. +
begin()* + Return an iterator pointing to the beginning of the circular buffer. +
end()* + Return an iterator pointing to the end of the circular buffer. +
rbegin()* + Return a reverse iterator pointing to the beginning of the reversed circular + buffer. +
rend()* + Return a reverse iterator pointing to the end of the reversed circular buffer. +
get_allocator()* + Return the allocator. +
operator=(const + circular_buffer& cb) + Assignment operator. +
swap(circular_buffer& + cb) + Swap the contents of two circular buffers. +
+ * The method also has its const counterpart. +
+
+
+

Friend Functions

+ + + + + + + + + + + + + +
+ Method + + Description +
operator<(const circular_buffer& lhs, const circular_buffer& rhs)Lexicographical comparison.
operator==(const circular_buffer& lhs, const circular_buffer& rhs) + Test two circular buffers for equality. +
+
+
+

Model of

+

Random Access + Container, + Front Insertion Sequence, + Back Insertion Sequence, + Assignable (SGI), + Equality Comparable, + LessThan Comparable (SGI) +

+
+

Type Requirements

+ +
+

Semantics

+

The behaviour of insertion for circular_buffer is as follows: +

+ +

The behaviour of resizing a circular_buffer is as follows: +

+ +

The behaviour of assigning to a circular_buffer is as follows: +

+ +

The rules for iterator (and result of data()) + invalidation for circular_buffer are as follows: +

+ +

In addition to the preceding rules the iterators get also invalidated due to + overwritting (e.g. iterator pointing to the front-most element gets invalidated + when inserting into the full circular_buffer). They get + invalidated in that sense they do not point to the same element as before but + they do still point to the same valid place in the memory. If you want + to rely on this feature you have to turn of the Debug Support + otherwise an assertion will report an error if such invalidated iterator is used.

+
+

Caveats

+

The circular_buffer should not be used for storing pointers to + dynamically allocated objects. When a circular_buffer becomes + full, further insertion will overwrite the stored pointers - resulting in a memory + leak. One recommend alternative is the use of smart pointers [1]. + (Any container of std::auto_ptr is considered particularly + hazardous. [2]) +

+

Elements inserted near the front of a full circular_buffer can be + lost. According to the semantics of insert, + insertion overwrites front-most items as necessary - possibly including + elements currently being inserted at the front of the buffer. + Conversely, push_front to a full circular_buffer is + guaranteed to overwrite the back-most element. +

+

Elements inserted near the back of a full circular_buffer can be + lost. According to the semantics of rinsert, + insertion overwrites front-most items as necessary - possibly including + elements currently being inserted at the back of the buffer. Conversely, + push_back to a full circular_buffer is guaranteed to + overwrite the front-most element. +

+

+

While internals of a circular_buffer are circular, iterators are not. + Iterators of a circular_buffer are only valid for the range [begin(), + end()]. E.g. iterators (begin() - 1) and (end() + 1) + are invalid. +

+
+

Debug Support

+

In order to help a programmer to avoid and find common bugs, the circular_buffer + contains a kind of debug support.

+

+ The circular_buffer maintains a list of valid iterators. As soon + as any element gets destroyed all iterators pointing to this element are + removed from this list and explicitly invalidated (an invalidation flag is + set). The debug support also consists of many assertions (BOOST_ASSERT + macros) which ensure the circular_buffer and its iterators are + used in the correct manner at runtime. In case an invalid iterator is used the + assertion will report an error. The connection of explicit iterator + invalidation and assertions makes a very robust debug technique which catches + most of the errors.

+

Moreover, the uninitialized memory allocated by circular_buffer is + filled with the value 0xcc in the debug mode. This can help the + programmer when debugging the code to recognize the initialized memory from the + uninitialized. For details refer the + source code. +

+

The debug support is enabled only in the debug mode (when the NDEBUG + is not defined). It can also be explicitly disabled by defining BOOST_DISABLE_CB_DEBUG + macro.

+
+

Example

+

The following example includes various usage of the circular_buffer. +

+
   #include <boost/circular_buffer.hpp>
+   #include <numeric>
+   #include <assert.h>
+
+   int main(int argc, char* argv[])
+   {
+      // create a circular buffer of capacity 3
+      boost::circular_buffer<int> cb(3); 
+
+      // insert some elements into the circular buffer
+      cb.push_back(1);
+      cb.push_back(2);
+
+      // assertions
+      assert(cb[0] == 1);
+      assert(cb[1] == 2);
+      assert(!cb.full());
+      assert(cb.size() == 2);
+      assert(cb.capacity() == 3);
+
+      // insert some other elements
+      cb.push_back(3);
+      cb.push_back(4);
+      int sum = std::accumulate(cb.begin(), cb.end(), 0); // evaluate sum
+
+      // assertions
+      assert(cb[0] == 2);
+      assert(cb[1] == 3);
+      assert(cb[2] == 4);
+      assert(sum == 9);
+      assert(cb.full());
+      assert(cb.size() == 3);
+      assert(cb.capacity() == 3);
+      return 0;
+   }
+
+

The circular_buffer has a capacity of three int. + Therefore, the size of the buffer will not exceed three. The + accumulate algorithm evaluates the sum of the stored + elements. The semantics the circular_buffer can be inferred from + the assertions. +

+
+

Notes

+

[1] A good implementation of smart pointers is included in + Boost. +

+

[2] Never create a circular buffer of std::auto_ptr. + Refer to Scott Meyers' excellent book Effective + STL for a detailed discussion. (Meyers S., Effective STL: 50 Specific + Ways to Improve Your Use of the Standard Template Library. + Addison-Wesley, 2001.) +

+
+

See also

+

boost::circular_buffer_space_optimized, + std::vector, + std::list, std::deque +

+
+

Acknowledgments

+

I would like to thank the Boost community for help when developing the circular_buffer.

+

The circular_buffer has a short history. Its first version was a std::deque + adaptor. This container was not very effective because of many reallocations + when inserting/removing an element. Thomas Wenish did a review of this version + and motivated me to create a circular buffer which allocates memory at once + when created.

+

The second version adapted std::vector but it has been abandoned + soon because of limited control over iterator invalidation.

+

The current version is a full-fledged STL compliant container. Pavel Vozenilek + did a thorough review of this version and came with many good ideas and + improvements. Also, I would like to thank Howard Hinnant and Nigel Stewart for + valuable comments and ideas. And once again I want to thank Nigel Stewart for + this document revision. +

+
+ Copyright © 2003-2004 Jan Gaspar + + diff --git a/doc/circular_buffer.png b/doc/circular_buffer.png new file mode 100644 index 0000000..1370a4b Binary files /dev/null and b/doc/circular_buffer.png differ diff --git a/doc/circular_buffer_adaptor.html b/doc/circular_buffer_adaptor.html new file mode 100644 index 0000000..98b7269 --- /dev/null +++ b/doc/circular_buffer_adaptor.html @@ -0,0 +1,203 @@ + + + + Space Optimized Circular Buffer Container Adaptor + + + +

Space Optimized Circular Buffer Container Adaptor

+ + + + + +
+

circular_buffer_space_optimized<T, Alloc>

+
+

Contents

+

   Synopsis
+    Rationale
+    Definition
+    Template Parameters, Members and Friend + Functions
+    Model of
+    Type Requirements
+    Semantics
+    See also
+    Acknowledgments +

+
+

Synopsis

+

The circular_buffer_space_optimized container is an adaptor of the + circular_buffer. The + functionality of the circular_buffer_space_optimized is similar to + the base circular_buffer except it does not allocate memory at + once when created rather it allocates memory as needed. (The predictive memory + allocation is similar to typical std::vector implementation.) + Moreover the memory is automatically freed as the size of the container + decreases. +

+ + + + + + + + + +
Figure:The memory allocation process of the space optimized circular + buffer. The min_capacity represents the minimal guaranteed amount + of allocated memory. The allocated memory will never drop under this value. By + default the min_capacity is set to 0. +
+
+
+

Rationale

+

The auto-resizing mode of the space optimized circular buffer can be useful in + situations when the container can possibly store large number of elements but + most of its lifetime the container stores just few of them. The usage of the circular_buffer_space_optimized + will result in decreased memory consumption and can improve the CPU cache + effectiveness. +

+
+

Definition

+

#include <boost/circular_buffer.hpp> +

+

In fact the circular_buffer_space_optimized is defined in the file + boost/circular_buffer/adaptor.hpp, + but it is necessary to include the boost/circular_buffer.hpp + in order to use this container. Also, there is a forward declaration for circular_buffer_space_optimized + in the header boost/circular_buffer_fwd.hpp. +

+
+

Template Parameters, Members and Friend Functions

+

Template parameters, members and friend functions of the circular_buffer_space_optimized + are almost the same as for the base circular_buffer. Refer the circular_buffer + documentation and also its + source code documentation for a detailed description. +

+

The specific methods of the circular_buffer_space_optimized are + listed below. +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ Method + + Description +
circular_buffer_space_optimized(size_type + capacity, size_type min_capacity = 0, const allocator_type& alloc = + allocator_type()) + Create an empty space optimized circular buffer with a given capacity. +
circular_buffer_space_optimized + (size_type capacity, size_type min_capacity, const T& item, const + allocator_type& alloc = allocator_type()) + Create a full space optimized circular buffer filled with copies of item. +
template<InputIterator> + circular_buffer_space_optimized(size_type capacity, size_type + min_capacity, InputIterator first, InputIterator last, const + allocator_type& alloc = allocator_type()) + Create a space optimized circular buffer with a copy of a range. +
min_capacity() + const + Return the minimal guaranteed amount of allocated memory. +
set_min_capacity() + Change the minimal guaranteed amount of allocated memory. +
+
+
+

Model of

+

Random Access + Container, + Front Insertion Sequence, + Back Insertion Sequence, + Assignable (SGI), + Equality Comparable, + LessThan Comparable (SGI) +

+
+

Type Requirements

+ +
+

Semantics

+

The behaviour of memory auto-resizing is as follows: +

+ +

The semantics of the circular_buffer_space_optimized then follows + the semantics of the base circular_buffer + except the invalidation rules. +

+

The rule for iterator invalidation for circular_buffer_space_optimized + is as follows: +

+ +
+

See also

+

boost::circular_buffer, + std::vector +

+
+

Acknowledgments

+

The idea of the space optimized circular buffer has been introduced by Pavel + Vozenilek. +

+
+ Copyright © 2003-2004 Jan Gaspar + + diff --git a/doc/circular_buffer_space_optimized.png b/doc/circular_buffer_space_optimized.png new file mode 100644 index 0000000..4f29f8c Binary files /dev/null and b/doc/circular_buffer_space_optimized.png differ diff --git a/doc/footer.html b/doc/footer.html new file mode 100644 index 0000000..1548804 --- /dev/null +++ b/doc/footer.html @@ -0,0 +1,12 @@ +
+ + + + + + + + + \ No newline at end of file diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 0000000..459e1e8 --- /dev/null +++ b/doc/header.html @@ -0,0 +1,19 @@ + + + + + $title + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
diff --git a/doc/srcdoc/adaptor_8hpp-source.html b/doc/srcdoc/adaptor_8hpp-source.html new file mode 100644 index 0000000..c27ac11 --- /dev/null +++ b/doc/srcdoc/adaptor_8hpp-source.html @@ -0,0 +1,432 @@ + + + + + adaptor.hpp Source File + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

adaptor.hpp

00001 // Implementation of the circular buffer adaptor.
+00002 
+00003 // Copyright (c) 2003-2004 Jan Gaspar
+00004 
+00005 // Use, modification, and distribution is subject to the Boost Software
+00006 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+00007 // http://www.boost.org/LICENSE_1_0.txt)
+00008 
+00009 #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
+00010 #define BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP
+00011 
+00012 #if defined(_MSC_VER) && _MSC_VER >= 1200
+00013     #pragma once
+00014 #endif
+00015 
+00016 namespace boost {
+00017 
+00031 template<class T, class Alloc>
+00032 class circular_buffer_space_optimized : private circular_buffer<T, Alloc> {
+00033 public:
+00034 // Typedefs
+00035 
+00036     typedef typename circular_buffer<T, Alloc>::value_type value_type;
+00037     typedef typename circular_buffer<T, Alloc>::pointer pointer;
+00038     typedef typename circular_buffer<T, Alloc>::const_pointer const_pointer;
+00039     typedef typename circular_buffer<T, Alloc>::reference reference;
+00040     typedef typename circular_buffer<T, Alloc>::const_reference const_reference;
+00041     typedef typename circular_buffer<T, Alloc>::size_type size_type;
+00042     typedef typename circular_buffer<T, Alloc>::difference_type difference_type;
+00043     typedef typename circular_buffer<T, Alloc>::allocator_type allocator_type;
+00044     typedef typename circular_buffer<T, Alloc>::param_value_type param_value_type;
+00045     typedef typename circular_buffer<T, Alloc>::const_iterator const_iterator;
+00046     typedef typename circular_buffer<T, Alloc>::iterator iterator;
+00047     typedef typename circular_buffer<T, Alloc>::const_reverse_iterator const_reverse_iterator;
+00048     typedef typename circular_buffer<T, Alloc>::reverse_iterator reverse_iterator;
+00049 
+00050 // Inherited
+00051 
+00052     using circular_buffer<T, Alloc>::get_allocator;
+00053     using circular_buffer<T, Alloc>::begin;
+00054     using circular_buffer<T, Alloc>::end;
+00055     using circular_buffer<T, Alloc>::rbegin;
+00056     using circular_buffer<T, Alloc>::rend;
+00057     using circular_buffer<T, Alloc>::at;
+00058     using circular_buffer<T, Alloc>::front;
+00059     using circular_buffer<T, Alloc>::back;
+00060     using circular_buffer<T, Alloc>::data;
+00061     using circular_buffer<T, Alloc>::size;
+00062     using circular_buffer<T, Alloc>::max_size;
+00063     using circular_buffer<T, Alloc>::empty;
+00064 
+00065 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+00066     reference operator [] (size_type n) { return circular_buffer<T, Alloc>::operator[](n); }
+00067     return_value_type operator [] (size_type n) const { return circular_buffer<T, Alloc>::operator[](n); }
+00068 #else
+00069     using circular_buffer<T, Alloc>::operator[];
+00070 #endif
+00071 
+00072 private:
+00073 // Member variables
+00074 
+00076     size_type m_capacity;
+00077 
+00079     size_type m_min_capacity;
+00080 
+00081 public:
+00082 // Overridden
+00083 
+00085     bool full() const { return size() == capacity(); }
+00086 
+00088 
+00091     size_type min_capacity() const { return m_min_capacity; }
+00092 
+00094 
+00102     void set_min_capacity(size_type new_min_capacity) {
+00103         BOOST_CB_ASSERT(capacity() >= new_min_capacity); // check for too large new min_capacity
+00104         m_min_capacity = new_min_capacity;
+00105         if (new_min_capacity > circular_buffer<T, Alloc>::capacity())
+00106             circular_buffer<T, Alloc>::set_capacity(new_min_capacity);
+00107         else
+00108             check_high_capacity();
+00109     }
+00110 
+00112     size_type capacity() const { return m_capacity; }
+00113 
+00114 #if defined(BOOST_CB_TEST)
+00115 
+00117 
+00121     size_type internal_capacity() const { return circular_buffer<T, Alloc>::capacity(); }
+00122 
+00123 #endif // #if defined(BOOST_CB_TEST)
+00124 
+00126 
+00132     void set_capacity(size_type new_capacity, bool remove_front = true) {
+00133         BOOST_CB_ASSERT(new_capacity >= min_capacity()); // check for too low new capacity
+00134         if (new_capacity < circular_buffer<T, Alloc>::capacity())
+00135             circular_buffer<T, Alloc>::set_capacity(new_capacity, remove_front);
+00136         m_capacity = new_capacity;
+00137     }
+00138 
+00140     void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) {
+00141         if (new_size > size()) {
+00142             if (new_size > capacity())
+00143                 m_capacity = new_size;
+00144             insert(end(), new_size - size(), item);
+00145         } else {
+00146             if (remove_front)
+00147                 erase(begin(), end() - new_size);
+00148             else
+00149                 erase(begin() + new_size, end());
+00150         }
+00151     }
+00152 
+00154 
+00167     explicit circular_buffer_space_optimized(
+00168         size_type capacity,
+00169         size_type min_capacity = 0,
+00170         const allocator_type& alloc = allocator_type())
+00171     : circular_buffer<T, Alloc>(min_capacity, alloc)
+00172     , m_capacity(capacity)
+00173     , m_min_capacity(min_capacity) {
+00174         BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity
+00175     }
+00176 
+00178 
+00192     circular_buffer_space_optimized(
+00193         size_type capacity,
+00194         size_type min_capacity,
+00195         param_value_type item,
+00196         const allocator_type& alloc = allocator_type())
+00197     : circular_buffer<T, Alloc>(capacity, item, alloc)
+00198     , m_capacity(capacity)
+00199     , m_min_capacity(min_capacity) {
+00200         BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity
+00201     }
+00202 
+00203     // Default copy constructor
+00204 
+00206 
+00227     template <class InputIterator>
+00228     circular_buffer_space_optimized(
+00229         size_type capacity,
+00230         size_type min_capacity,
+00231         InputIterator first,
+00232         InputIterator last,
+00233         const allocator_type& alloc = allocator_type())
+00234     : circular_buffer<T, Alloc>(
+00235         init_capacity(capacity, min_capacity, first, last), first, last, alloc)
+00236     , m_capacity(capacity)
+00237     , m_min_capacity(min_capacity) {
+00238         BOOST_CB_ASSERT(capacity >= min_capacity);        // check for capacity lower than min_capacity
+00239         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
+00240     }
+00241 
+00242     // Default destructor
+00243 
+00244     // Default assign operator
+00245 
+00247     void assign(size_type n, param_value_type item) {
+00248         if (n > m_capacity)
+00249             m_capacity = n;
+00250         circular_buffer<T, Alloc>::assign(n, item);
+00251     }
+00252 
+00254     template <class InputIterator>
+00255     void assign(InputIterator first, InputIterator last) {
+00256         circular_buffer<T, Alloc>::assign(first, last);
+00257         size_type capacity = circular_buffer<T, Alloc>::capacity();
+00258         if (capacity > m_capacity)
+00259             m_capacity = capacity;
+00260     }
+00261 
+00263     void swap(circular_buffer_space_optimized& cb) {
+00264         std::swap(m_capacity, cb.m_capacity);
+00265         std::swap(m_min_capacity, cb.m_min_capacity);
+00266         circular_buffer<T, Alloc>::swap(cb);
+00267     }
+00268 
+00270 
+00275     void push_back(param_value_type item) {
+00276         check_low_capacity();
+00277         circular_buffer<T, Alloc>::push_back(item);
+00278     }
+00279 
+00281 
+00286     void push_back() { push_back(value_type()); }
+00287 
+00289 
+00294     void push_front(param_value_type item) {
+00295         check_low_capacity();
+00296         circular_buffer<T, Alloc>::push_front(item);
+00297     }
+00298 
+00300 
+00305     void push_front() { push_front(value_type()); }
+00306 
+00308 
+00313     void pop_back() {
+00314         circular_buffer<T, Alloc>::pop_back();
+00315         check_high_capacity();
+00316     }
+00317 
+00319 
+00324     void pop_front() {
+00325         circular_buffer<T, Alloc>::pop_front();
+00326         check_high_capacity();
+00327     }
+00328 
+00330 
+00335     iterator insert(iterator pos, param_value_type item) {
+00336         size_type index = pos - begin();
+00337         check_low_capacity();
+00338         return circular_buffer<T, Alloc>::insert(begin() + index, item);
+00339     }
+00340 
+00342 
+00347     iterator insert(iterator pos) { return insert(pos, value_type()); }
+00348 
+00350 
+00355     void insert(iterator pos, size_type n, param_value_type item) {
+00356         size_type index = pos - begin();
+00357         check_low_capacity(n);
+00358         circular_buffer<T, Alloc>::insert(begin() + index, n, item);
+00359     }
+00360 
+00362 
+00367     template <class InputIterator>
+00368     void insert(iterator pos, InputIterator first, InputIterator last) {
+00369         insert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
+00370     }
+00371 
+00373 
+00378     iterator rinsert(iterator pos, param_value_type item) {
+00379         size_type index = pos - begin();
+00380         check_low_capacity();
+00381         return circular_buffer<T, Alloc>::rinsert(begin() + index, item);
+00382     }
+00383 
+00385 
+00390     iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
+00391 
+00393 
+00398     void rinsert(iterator pos, size_type n, param_value_type item) {
+00399         size_type index = pos - begin();
+00400         check_low_capacity(n);
+00401         circular_buffer<T, Alloc>::rinsert(begin() + index, n, item);
+00402     }
+00403 
+00405 
+00410     template <class InputIterator>
+00411     void rinsert(iterator pos, InputIterator first, InputIterator last) {
+00412         rinsert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
+00413     }
+00414 
+00416 
+00421     iterator erase(iterator pos) {
+00422         iterator it = circular_buffer<T, Alloc>::erase(pos);
+00423         size_type index = it - begin();
+00424         check_high_capacity();
+00425         return begin() + index;
+00426     }
+00427 
+00429 
+00434     iterator erase(iterator first, iterator last) {
+00435         iterator it = circular_buffer<T, Alloc>::erase(first, last);
+00436         size_type index = it - begin();
+00437         check_high_capacity();
+00438         return begin() + index;
+00439     }
+00440 
+00442     void clear() { erase(begin(), end()); }
+00443 
+00444 private:
+00445 // Helper methods
+00446 
+00448     size_type ensure_reserve(size_type new_capacity, size_type size) const {
+00449         if (size + new_capacity / 5 >= new_capacity)
+00450             new_capacity *= 2; // ensure at least 20% reserve
+00451         if (new_capacity > capacity())
+00452             return capacity();
+00453         return new_capacity;
+00454     }
+00455 
+00457     /*
+00458         \post If the capacity is low it will be increased.
+00459     */
+00460     void check_low_capacity(size_type n = 1) {
+00461         size_type new_size = size() + n;
+00462         size_type new_capacity = circular_buffer<T, Alloc>::capacity();
+00463         if (new_size > new_capacity) {
+00464             if (new_capacity == 0)
+00465                 new_capacity = 1;
+00466             for (; new_size > new_capacity; new_capacity *= 2);
+00467             circular_buffer<T, Alloc>::set_capacity(
+00468                 ensure_reserve(new_capacity, new_size));
+00469         }
+00470     }
+00471 
+00473     /*
+00474         \post If the capacity is high it will be decreased.
+00475     */
+00476     void check_high_capacity() {
+00477         size_type new_capacity = circular_buffer<T, Alloc>::capacity();
+00478         while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations
+00479             new_capacity /= 2;
+00480             if (new_capacity <= min_capacity()) {
+00481                 new_capacity = min_capacity();
+00482                 break;
+00483             }
+00484         }
+00485         circular_buffer<T, Alloc>::set_capacity(
+00486             ensure_reserve(new_capacity, size()));
+00487     }
+00488 
+00490     template <class InputIterator>
+00491     static size_type init_capacity(size_type capacity, size_type min_capacity, InputIterator first, InputIterator last) {
+00492         BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
+00493         return std::min(capacity, std::max(min_capacity,
+00494             static_cast<size_type>(std::distance(first, last))));
+00495     }
+00496 
+00498     template <class InputIterator>
+00499     void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
+00500         insert(pos, (size_type)n, item);
+00501     }
+00502 
+00504     template <class InputIterator>
+00505     void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
+00506         size_type index = pos - begin();
+00507         check_low_capacity(std::distance(first, last));
+00508         circular_buffer<T, Alloc>::insert(begin() + index, first, last);
+00509     }
+00510 
+00512     template <class InputIterator>
+00513     void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
+00514         rinsert(pos, (size_type)n, item);
+00515     }
+00516 
+00518     template <class InputIterator>
+00519     void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
+00520         size_type index = pos - begin();
+00521         check_low_capacity(std::distance(first, last));
+00522         circular_buffer<T, Alloc>::rinsert(begin() + index, first, last);
+00523     }
+00524 };
+00525 
+00526 // Non-member functions
+00527 
+00529 template <class T, class Alloc>
+00530 inline bool operator == (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00531                          const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00532     return lhs.size() == rhs.size() &&
+00533         std::equal(lhs.begin(), lhs.end(), rhs.begin());
+00534 }
+00535 
+00537 template <class T, class Alloc>
+00538 inline bool operator < (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00539                         const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00540     return std::lexicographical_compare(
+00541         lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+00542 }
+00543 
+00544 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
+00545 
+00547 template <class T, class Alloc>
+00548 inline bool operator != (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00549                          const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00550     return !(lhs == rhs);
+00551 }
+00552 
+00554 template <class T, class Alloc>
+00555 inline bool operator > (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00556                         const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00557     return rhs < lhs;
+00558 }
+00559 
+00561 template <class T, class Alloc>
+00562 inline bool operator <= (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00563                          const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00564     return !(rhs < lhs);
+00565 }
+00566 
+00568 template <class T, class Alloc>
+00569 inline bool operator >= (const circular_buffer_space_optimized<T, Alloc>& lhs,
+00570                          const circular_buffer_space_optimized<T, Alloc>& rhs) {
+00571     return !(lhs < rhs);
+00572 }
+00573 
+00575 template <class T, class Alloc>
+00576 inline void swap(circular_buffer_space_optimized<T, Alloc>& lhs,
+00577                  circular_buffer_space_optimized<T, Alloc>& rhs) {
+00578     lhs.swap(rhs);
+00579 }
+00580 
+00581 #endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
+00582 
+00583 } // namespace boost
+00584 
+00585 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP)
+

+ + + + + + + + + diff --git a/doc/srcdoc/annotated.html b/doc/srcdoc/annotated.html new file mode 100644 index 0000000..2af82e4 --- /dev/null +++ b/doc/srcdoc/annotated.html @@ -0,0 +1,37 @@ + + + + + Annotated Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

Circular Buffer Class List

Here are the classes, structs, unions and interfaces with brief descriptions: + + +
boost::circular_buffer< T, Alloc >Circular buffer - a STL compliant container
boost::circular_buffer_space_optimized< T, Alloc >Space optimized circular buffer container adaptor
+
+ + + + + + + + + diff --git a/doc/srcdoc/base_8hpp-source.html b/doc/srcdoc/base_8hpp-source.html new file mode 100644 index 0000000..c8108df --- /dev/null +++ b/doc/srcdoc/base_8hpp-source.html @@ -0,0 +1,1077 @@ + + + + + base.hpp Source File + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

base.hpp

00001 // Implementation of the base circular buffer.
+00002 
+00003 // Copyright (c) 2003-2004 Jan Gaspar
+00004 
+00005 // Use, modification, and distribution is subject to the Boost Software
+00006 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+00007 // http://www.boost.org/LICENSE_1_0.txt)
+00008 
+00009 #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
+00010 #define BOOST_CIRCULAR_BUFFER_BASE_HPP
+00011 
+00012 #if defined(_MSC_VER) && _MSC_VER >= 1200
+00013     #pragma once
+00014 #endif
+00015 
+00016 #include <boost/call_traits.hpp>
+00017 #include <boost/concept_check.hpp>
+00018 #include <boost/throw_exception.hpp>
+00019 #include <boost/iterator/reverse_iterator.hpp>
+00020 #include <algorithm>
+00021 #if !defined(BOOST_NO_EXCEPTIONS)
+00022     #include <stdexcept>
+00023 #endif
+00024 #if BOOST_CB_ENABLE_DEBUG
+00025     #include <string.h>
+00026 #endif
+00027 
+00028 namespace boost {
+00029 
+00042 template <class T, class Alloc>
+00043 class circular_buffer : cb_details::cb_iterator_registry {
+00044 
+00045 // Requirements
+00046     BOOST_CLASS_REQUIRE(T, boost, CopyConstructibleConcept);
+00047 
+00048 public:
+00049 // Basic types
+00050 
+00052     typedef typename Alloc::value_type value_type;
+00053 
+00055     typedef typename Alloc::pointer pointer;
+00056 
+00058     typedef typename Alloc::const_pointer const_pointer;
+00059 
+00061     typedef typename Alloc::reference reference;
+00062 
+00064     typedef typename Alloc::const_reference const_reference;
+00065 
+00067 
+00070     typedef typename Alloc::difference_type difference_type;
+00071 
+00073 
+00076     typedef typename Alloc::size_type size_type;
+00077 
+00079     typedef Alloc allocator_type;
+00080 
+00082     allocator_type get_allocator() const { return m_alloc; }
+00083 
+00085 
+00089     allocator_type& get_allocator() { return m_alloc; }
+00090 
+00091 // Helper types
+00092 
+00093     // Define a type that represents the "best" way to pass the value_type to a method.
+00094     typedef typename call_traits<value_type>::param_type param_value_type;
+00095 
+00096     // Define a type that represents the "best" way to return the value_type from a const method.
+00097     typedef typename call_traits<value_type>::param_type return_value_type;
+00098 
+00099 // Iterators
+00100 
+00102     typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_const_traits<Alloc> > const_iterator;
+00103 
+00105     typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_nonconst_traits<Alloc> > iterator;
+00106 
+00108     typedef reverse_iterator<const_iterator> const_reverse_iterator;
+00109 
+00111     typedef reverse_iterator<iterator> reverse_iterator;
+00112 
+00113 private:
+00114 // Member variables
+00115 
+00117     pointer m_buff;
+00118 
+00120     pointer m_end;
+00121 
+00123     pointer m_first;
+00124 
+00126     pointer m_last;
+00127 
+00129     size_type m_size;
+00130 
+00132     allocator_type m_alloc;
+00133 
+00134 // Friends
+00135 #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+00136     friend iterator;
+00137     friend const_iterator;
+00138 #else
+00139     friend struct iterator;
+00140     friend struct const_iterator;
+00141 #endif
+00142 
+00143 public:
+00144 // Element access
+00145 
+00147     iterator begin() { return iterator(this, empty() ? 0 : m_first); }
+00148 
+00150     iterator end() { return iterator(this, 0); }
+00151 
+00153     const_iterator begin() const { return const_iterator(this, empty() ? 0 : m_first); }
+00154 
+00156     const_iterator end() const { return const_iterator(this, 0); }
+00157 
+00159     reverse_iterator rbegin() { return reverse_iterator(end()); }
+00160 
+00162     reverse_iterator rend() { return reverse_iterator(begin()); }
+00163     
+00165     const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+00166 
+00168     const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+00169 
+00171 
+00174     reference operator [] (size_type index) {
+00175         BOOST_CB_ASSERT(index < size()); // check for invalid index
+00176         return *add(m_first, index);
+00177     }
+00178 
+00180 
+00183     return_value_type operator [] (size_type index) const {
+00184         BOOST_CB_ASSERT(index < size()); // check for invalid index
+00185         return *add(m_first, index);
+00186     }
+00187 
+00189 
+00192     reference at(size_type index) {
+00193         check_position(index);
+00194         return (*this)[index];
+00195     }
+00196 
+00198 
+00201     return_value_type at(size_type index) const {
+00202         check_position(index);
+00203         return (*this)[index];
+00204     }
+00205 
+00207 
+00210     reference front() {
+00211         BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
+00212         return *m_first;
+00213     }
+00214 
+00216 
+00219     reference back() {
+00220         BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
+00221         return *((m_last == m_buff ? m_end : m_last) - 1);
+00222     }
+00223 
+00225 
+00228     return_value_type front() const {
+00229         BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
+00230         return *m_first;
+00231     }
+00232 
+00234 
+00237     return_value_type back() const {
+00238         BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
+00239         return *((m_last == m_buff ? m_end : m_last) - 1);
+00240     }
+00241 
+00243 
+00251     pointer data() {
+00252         if (empty())
+00253             return 0;
+00254         if (m_first < m_last || m_last == m_buff)
+00255             return m_first;
+00256         size_type constructed = 0;
+00257         pointer src = m_first;
+00258         pointer dest = m_buff;
+00259         pointer tmp = 0;
+00260         BOOST_CB_TRY
+00261         tmp = allocate(1);
+00262         for (pointer first = m_first; dest < src; src = first) {
+00263             for (size_type ii = 0; src < m_end; ++src, ++dest, ++ii) {
+00264                 if (dest == first) {
+00265                     first += ii;
+00266                     break;
+00267                 }
+00268                 if (is_uninitialized(dest)) {
+00269                     m_alloc.construct(dest, *src);
+00270                     ++constructed;
+00271                 } else {
+00272                     m_alloc.construct(tmp, *src);
+00273                     BOOST_CB_TRY
+00274                     replace(src, *dest);
+00275                     BOOST_CB_UNWIND(
+00276                         destroy_item(tmp);
+00277                         tidy(src);
+00278                     )
+00279                     BOOST_CB_TRY
+00280                     replace(dest, *tmp);
+00281                     BOOST_CB_UNWIND(
+00282                         destroy_item(tmp);
+00283                         tidy(dest);
+00284                     )
+00285                     destroy_item(tmp);
+00286                 }
+00287             }
+00288         }
+00289         deallocate(tmp, 1);
+00290         BOOST_CB_UNWIND(
+00291             deallocate(tmp, 1);
+00292             m_last += constructed;
+00293             m_size += constructed;
+00294         )
+00295         for (dest = m_buff + size(); dest < m_end; ++dest)
+00296             destroy_item(dest);
+00297         m_first = m_buff;
+00298         m_last = add(m_buff, size());
+00299         return m_buff;
+00300     }
+00301 
+00302 // Size and capacity
+00303 
+00305     size_type size() const { return m_size; }
+00306 
+00308     size_type max_size() const { return m_alloc.max_size(); }
+00309     
+00311 
+00315     bool empty() const { return size() == 0; }
+00316 
+00318 
+00323     bool full() const { return size() == capacity(); }
+00324 
+00326     size_type capacity() const { return m_end - m_buff; }
+00327 
+00329 
+00347     void set_capacity(size_type new_capacity, bool remove_front = true) {
+00348         if (new_capacity == capacity())
+00349             return;
+00350         pointer buff = allocate(new_capacity);
+00351         size_type new_size = std::min(new_capacity, size());
+00352         BOOST_CB_TRY
+00353         if (remove_front)
+00354             cb_details::uninitialized_copy(end() - new_size, end(), buff, m_alloc);
+00355         else
+00356             cb_details::uninitialized_copy(begin(), begin() + new_size, buff, m_alloc);
+00357         BOOST_CB_UNWIND(deallocate(buff, new_capacity))
+00358         destroy();
+00359         m_size = new_size;
+00360         m_buff = m_first = buff;
+00361         m_end = m_buff + new_capacity;
+00362         m_last = add(m_buff, size());
+00363     }
+00364 
+00366 
+00387     void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) {
+00388         if (new_size > size()) {
+00389             if (new_size > capacity())
+00390                 set_capacity(new_size);
+00391             insert(end(), new_size - size(), item);
+00392         } else {
+00393             if (remove_front)
+00394                 erase(begin(), end() - new_size);
+00395             else
+00396                 erase(begin() + new_size, end());
+00397         }
+00398     }
+00399 
+00400 // Construction/Destruction
+00401 
+00403 
+00407     explicit circular_buffer(
+00408         size_type capacity,
+00409         const allocator_type& alloc = allocator_type())
+00410     : m_size(0), m_alloc(alloc) {
+00411         m_first = m_last = m_buff = allocate(capacity);
+00412         m_end = m_buff + capacity;
+00413     }
+00414 
+00416 
+00421     circular_buffer(
+00422         size_type capacity,
+00423         param_value_type item,
+00424         const allocator_type& alloc = allocator_type())
+00425     : m_size(capacity), m_alloc(alloc) {
+00426         m_first = m_last = m_buff = allocate(capacity);
+00427         m_end = m_buff + capacity;
+00428         BOOST_CB_TRY
+00429         cb_details::uninitialized_fill_n(m_buff, size(), item, m_alloc);
+00430         BOOST_CB_UNWIND(deallocate(m_buff, capacity))
+00431     }
+00432 
+00434 
+00439     circular_buffer(const circular_buffer<T, Alloc>& cb)
+00440     : m_size(cb.size()), m_alloc(cb.get_allocator()) {
+00441         m_first = m_last = m_buff = allocate(cb.capacity());
+00442         BOOST_CB_TRY
+00443         m_end = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc);
+00444         BOOST_CB_UNWIND(deallocate(m_buff, cb.capacity()))
+00445     }
+00446 
+00448 
+00458     template <class InputIterator>
+00459     circular_buffer(
+00460         size_type capacity,
+00461         InputIterator first,
+00462         InputIterator last,
+00463         const allocator_type& alloc = allocator_type())
+00464     : m_alloc(alloc) {
+00465         BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
+00466         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
+00467         m_first = m_buff = allocate(capacity);
+00468         m_end = m_buff + capacity;
+00469         size_type diff = std::distance(first, last);
+00470         if (diff > capacity) {
+00471             std::advance(first, diff - capacity);
+00472             m_size = capacity;
+00473             m_last = m_buff;
+00474         } else {
+00475             m_size = diff;
+00476             if (diff == capacity)
+00477                 m_last = m_buff;
+00478             else
+00479                 m_last = m_buff + size();
+00480         }
+00481         BOOST_CB_TRY
+00482         cb_details::uninitialized_copy(first, last, m_buff, m_alloc);
+00483         BOOST_CB_UNWIND(deallocate(m_buff, capacity))
+00484     }
+00485 
+00487     ~circular_buffer() { destroy(); }
+00488 
+00489 private:
+00490 // Helper functors
+00491 
+00492     // Functor for assigning n items.
+00493     struct assign_n {
+00494         size_type m_n;
+00495         param_value_type m_item;
+00496         allocator_type& m_alloc;
+00497         explicit assign_n(size_type n, param_value_type item, allocator_type& alloc) : m_n(n), m_item(item), m_alloc(alloc) {}
+00498         void operator () (pointer p) const {
+00499             cb_details::uninitialized_fill_n(p, m_n, m_item, m_alloc);
+00500         }
+00501     private:
+00502         assign_n& operator = (const assign_n&); // do not generate
+00503     };
+00504 
+00505     // Functor for assigning range of items.
+00506     template <class InputIterator>
+00507     struct assign_range {
+00508         InputIterator m_first;
+00509         InputIterator m_last;
+00510         allocator_type& m_alloc;
+00511         explicit assign_range(InputIterator first, InputIterator last, allocator_type& alloc) : m_first(first), m_last(last), m_alloc(alloc) {}
+00512         void operator () (pointer p) const {
+00513             cb_details::uninitialized_copy(m_first, m_last, p, m_alloc);
+00514         }
+00515     private:
+00516         assign_range& operator = (const assign_range&); // do not generate
+00517     };
+00518 
+00519 public:
+00520 // Assign methods
+00521 
+00523 
+00529     circular_buffer<T, Alloc>& operator = (const circular_buffer<T, Alloc>& cb) {
+00530         if (this == &cb)
+00531             return *this;
+00532         pointer buff = allocate(cb.capacity());
+00533         BOOST_CB_TRY
+00534         pointer last = cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc);
+00535         destroy();
+00536         m_size = cb.size();
+00537         m_first = m_buff = buff;
+00538         m_end = m_buff + cb.capacity();
+00539         m_last = full() ? m_buff : last;
+00540         BOOST_CB_UNWIND(deallocate(buff, cb.capacity()))
+00541         return *this;
+00542     }
+00543 
+00545 
+00555     void assign(size_type n, param_value_type item) { do_assign(n, assign_n(n, item, m_alloc)); }
+00556     
+00558 
+00568     template <class InputIterator>
+00569     void assign(InputIterator first, InputIterator last) {
+00570         assign(first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
+00571     }
+00572 
+00574 
+00578     void swap(circular_buffer& cb) {
+00579         std::swap(m_alloc, cb.m_alloc); // in general this is not necessary,
+00580                                         // because allocators should not have state
+00581         std::swap(m_buff, cb.m_buff);
+00582         std::swap(m_end, cb.m_end);
+00583         std::swap(m_first, cb.m_first);
+00584         std::swap(m_last, cb.m_last);
+00585         std::swap(m_size, cb.m_size);
+00586 #if BOOST_CB_ENABLE_DEBUG
+00587         invalidate_all_iterators();
+00588         cb.invalidate_all_iterators();
+00589 #endif
+00590     }
+00591 
+00592 // push and pop
+00593 
+00595 
+00601     void push_back(param_value_type item) {
+00602         if (full()) {
+00603             if (empty())
+00604                 return;
+00605             replace_last(item);
+00606             increment(m_last);
+00607             m_first = m_last;
+00608         } else {
+00609             m_alloc.construct(m_last, item);
+00610             increment(m_last);
+00611             ++m_size;
+00612         }
+00613     }
+00614 
+00616 
+00622     void push_back() { push_back(value_type()); }
+00623 
+00625 
+00631     void push_front(param_value_type item) {
+00632         if (full()) {
+00633             if (empty())
+00634                 return;
+00635             replace_first(item);
+00636             m_last = m_first;
+00637         } else {
+00638             decrement(m_first);
+00639             BOOST_CB_TRY
+00640             m_alloc.construct(m_first, item);
+00641             BOOST_CB_UNWIND(increment(m_first))
+00642             ++m_size;
+00643         }
+00644     }
+00645 
+00647 
+00653     void push_front() { push_front(value_type()); }
+00654 
+00656 
+00662     void pop_back() {
+00663         BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
+00664         decrement(m_last);
+00665         destroy_item(m_last);
+00666         --m_size;
+00667     }
+00668 
+00670 
+00676     void pop_front() {
+00677         BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
+00678         destroy_item(m_first);
+00679         increment(m_first);
+00680         --m_size;
+00681     }
+00682 
+00683 private:
+00684 // Helper wrappers
+00685 
+00686     // Iterator dereference wrapper.
+00687     template <class InputIterator>
+00688     struct iterator_wrapper {
+00689         mutable InputIterator m_it;
+00690         explicit iterator_wrapper(InputIterator it) : m_it(it) {}
+00691         InputIterator get_reference() const { return m_it++; }
+00692     };
+00693 
+00694     // Item dereference wrapper.
+00695     struct item_wrapper {
+00696         const_pointer m_item;
+00697         explicit item_wrapper(param_value_type item) : m_item(&item) {}
+00698         const_pointer get_reference() const { return m_item; }
+00699     };
+00700 
+00701 public:
+00702 // Insert
+00703 
+00705 
+00714     iterator insert(iterator pos, param_value_type item) {
+00715         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00716         if (full() && pos == begin())
+00717             return begin();
+00718         if (pos.m_it == 0) {
+00719             if (full())
+00720                 replace_last(item);
+00721             else
+00722                 m_alloc.construct(m_last, item);
+00723             pos.m_it = m_last;
+00724         } else {
+00725             pointer src = m_last;
+00726             pointer dest = m_last;
+00727             BOOST_CB_TRY
+00728             while (src != pos.m_it) {
+00729                 decrement(src);
+00730                 if (dest == m_last && !full())
+00731                     m_alloc.construct(dest, *src);
+00732                 else
+00733                     replace(dest, *src);
+00734                 decrement(dest);
+00735             }
+00736             replace(pos.m_it, item);
+00737             BOOST_CB_UNWIND(
+00738                 if (dest == m_last) {
+00739                     if (full()) {
+00740                         increment(m_first);
+00741                         --m_size;
+00742                     }
+00743                 } else {
+00744                     if (!full()) {
+00745                         increment(m_last);
+00746                         ++m_size;
+00747                     }
+00748                     tidy(dest);
+00749                 }
+00750             )
+00751         }
+00752         increment(m_last);
+00753         if (full())
+00754             m_first = m_last;
+00755         else
+00756             ++m_size;
+00757         return iterator(this, pos.m_it);
+00758     }
+00759 
+00761 
+00769     iterator insert(iterator pos) { return insert(pos, value_type()); }
+00770 
+00772 
+00790     void insert(iterator pos, size_type n, param_value_type item) {
+00791         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00792         if (n == 0)
+00793             return;
+00794         size_type copy = capacity() - (end() - pos);
+00795         if (copy == 0)
+00796             return;
+00797         if (n > copy)
+00798             n = copy;
+00799         insert_n_item(pos, n, item_wrapper(item));
+00800     }
+00801 
+00803 
+00824     template <class InputIterator>
+00825     void insert(iterator pos, InputIterator first, InputIterator last) {
+00826         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00827         insert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
+00828     }
+00829 
+00831 
+00840     iterator rinsert(iterator pos, param_value_type item) {
+00841         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00842         if (full() && pos == end())
+00843             return end();
+00844         if (pos == begin()) {
+00845             if (full()) {
+00846                 replace_first(item);
+00847             } else {
+00848                 decrement(m_first);
+00849                 BOOST_CB_TRY
+00850                 m_alloc.construct(m_first, item);
+00851                 BOOST_CB_UNWIND(increment(m_first))
+00852             }
+00853         } else {
+00854             pointer src = m_first;
+00855             pointer dest = m_first;
+00856             decrement(dest);
+00857             pointer it = map_pointer(pos.m_it);
+00858             pointer first = m_first;
+00859             decrement(first);
+00860             BOOST_CB_TRY
+00861             while (src != it) {
+00862                 if (dest == first && !full())
+00863                     m_alloc.construct(dest, *src);
+00864                 else
+00865                     replace(dest, *src);
+00866                 increment(src);
+00867                 increment(dest);
+00868             }
+00869             replace((--pos).m_it, item);
+00870             BOOST_CB_UNWIND(
+00871                 if (dest == first) {
+00872                     if (full()) {
+00873                         decrement(m_last);
+00874                         --m_size;
+00875                     }
+00876                 } else {
+00877                     if (!full()) {
+00878                         m_first = first;
+00879                         ++m_size;
+00880                     }
+00881                     tidy(dest);
+00882                 }
+00883             )
+00884             decrement(m_first);
+00885         }
+00886         if (full())
+00887             m_last = m_first;
+00888         else
+00889             ++m_size;
+00890         return iterator(this, pos.m_it);
+00891     }
+00892 
+00894 
+00902     iterator rinsert(iterator pos) { return rinsert(pos, value_type()); }
+00903 
+00905 
+00923     void rinsert(iterator pos, size_type n, param_value_type item) {
+00924         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00925         rinsert_n_item(pos, n, item_wrapper(item));
+00926     }
+00927 
+00929 
+00950     template <class InputIterator>
+00951     void rinsert(iterator pos, InputIterator first, InputIterator last) {
+00952         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00953         rinsert(pos, first, last, cb_details::cb_iterator_category_traits<InputIterator>::tag());
+00954     }
+00955 
+00956 // Erase
+00957 
+00959 
+00968     iterator erase(iterator pos) {
+00969         BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator
+00970         BOOST_CB_ASSERT(pos.m_it != 0);  // check for iterator pointing to end()
+00971         pointer next = pos.m_it;
+00972         increment(next);
+00973         for (pointer p = pos.m_it; next != m_last; p = next, increment(next))
+00974             replace(p, *next);
+00975         decrement(m_last);
+00976         destroy_item(m_last);
+00977         --m_size;
+00978 #if BOOST_CB_ENABLE_DEBUG
+00979         return empty() ? end() : iterator(this, pos.m_it);
+00980 #else
+00981         return empty() ? end() : pos;
+00982 #endif
+00983     }
+00984 
+00986 
+00995     iterator erase(iterator first, iterator last) {
+00996         BOOST_CB_ASSERT(first.is_valid());            // check for uninitialized or invalidated iterator
+00997         BOOST_CB_ASSERT(last.is_valid());             // check for uninitialized or invalidated iterator
+00998         BOOST_CB_ASSERT(first.m_buff == last.m_buff); // check for iterators of different containers
+00999         BOOST_CB_ASSERT(first <= last);               // check for wrong range
+01000         if (first == last)
+01001             return first;
+01002         pointer tmp = first.m_it;
+01003         difference_type diff = last - first;
+01004         while (last.m_it != 0)
+01005             replace((first++).m_it, *last++);
+01006         while (first.m_it != 0)
+01007             destroy_item((first++).m_it);
+01008         m_last = sub(m_last, diff);
+01009         m_size -= diff;
+01010         return empty() ? end() : iterator(this, tmp);
+01011     }
+01012 
+01014 
+01018     void clear() {
+01019         destroy_content();
+01020         m_first = m_last = m_buff;
+01021         m_size = 0;
+01022     }
+01023 
+01024 private:
+01025 // Debug support
+01026 
+01027 #if BOOST_CB_ENABLE_DEBUG
+01028     
+01029     // Predicate determining if the condition for iterator invalidation has been met.
+01030     struct is_invalid_condition {
+01031         pointer m_p;
+01032         explicit is_invalid_condition(pointer p) : m_p(p) {}
+01033         bool operator () (const cb_details::cb_iterator_base* p) const {
+01034             return ((iterator*)p)->m_it == m_p;
+01035         }
+01036     };
+01037 
+01038 #endif // #if BOOST_CB_ENABLE_DEBUG
+01039 
+01040 // Helper methods
+01041 
+01043     void check_position(size_type index) const {
+01044         if (index >= size())
+01045             throw_exception(std::out_of_range("circular_buffer"));
+01046     }
+01047 
+01049     template <class Pointer0>
+01050     void increment(Pointer0& p) const {
+01051         if (++p == m_end)
+01052             p = m_buff;
+01053     }
+01054 
+01056     template <class Pointer0>
+01057     void decrement(Pointer0& p) const {
+01058         if (p == m_buff)
+01059             p = m_end;
+01060         --p;
+01061     }
+01062 
+01064     template <class Pointer0>
+01065     Pointer0 add(Pointer0 p, difference_type n) const {
+01066         return p + (n < (m_end - p) ? n : n - capacity());
+01067     }
+01068 
+01070     template <class Pointer0>
+01071     Pointer0 sub(Pointer0 p, difference_type n) const {
+01072         return p - (n > (p - m_buff) ? n - capacity() : n);
+01073     }
+01074 
+01076     pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; }
+01077 
+01079     bool is_uninitialized(const_pointer p) const {
+01080         return p >= m_last && (m_first < m_last || p < m_first);
+01081     }
+01082 
+01084 
+01087     void create_or_replace(pointer pos, param_value_type item) {
+01088         if (is_uninitialized(pos))
+01089             m_alloc.construct(pos, item);
+01090         else
+01091             replace(pos, item);
+01092     }
+01093 
+01095 
+01098     void destroy_created(pointer pos) {
+01099         if (is_uninitialized(pos))
+01100             destroy_item(pos);
+01101     }
+01102 
+01104     void replace(pointer pos, param_value_type item) {
+01105         replace(pos, item, cb_details::cb_replace_category_traits<value_type>::tag()); // invoke optimized operation for given type
+01106 #if BOOST_CB_ENABLE_DEBUG
+01107         invalidate_iterators(is_invalid_condition(pos));
+01108 #endif
+01109     }
+01110 
+01112     void replace(pointer pos, param_value_type item, cb_details::cb_destroy_tag) {
+01113         m_alloc.destroy(pos);
+01114         m_alloc.construct(pos, item);
+01115     }
+01116 
+01118     void replace(pointer pos, param_value_type item, cb_details::cb_assign_tag) {
+01119         *pos = item;
+01120     }
+01121 
+01123     void replace_first(param_value_type item) {
+01124         decrement(m_first);
+01125         BOOST_CB_TRY
+01126         replace(m_first, item);
+01127         BOOST_CB_UNWIND(
+01128             increment(m_first);
+01129             decrement(m_last);
+01130             --m_size;
+01131         )
+01132     }
+01133 
+01135     void replace_last(param_value_type item) {
+01136         BOOST_CB_TRY
+01137         replace(m_last, item);
+01138         BOOST_CB_UNWIND(
+01139             decrement(m_last);
+01140             --m_size;
+01141         )
+01142     }
+01143 
+01145     void tidy(pointer p) {
+01146         for (; m_first != p; increment(m_first), --m_size)
+01147             destroy_item(m_first);
+01148         increment(m_first);
+01149         --m_size;
+01150     }
+01151 
+01153     pointer allocate(size_type n) {
+01154         if (n > max_size())
+01155             throw_exception(std::length_error("circular_buffer"));
+01156 #if BOOST_CB_ENABLE_DEBUG
+01157         pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
+01158         ::memset(p, cb_details::CB_Unitialized, sizeof(value_type) * n);
+01159         return p;
+01160 #else
+01161         return (n == 0) ? 0 : m_alloc.allocate(n, 0);
+01162 #endif
+01163     }
+01164 
+01166     void deallocate(pointer p, size_type n) {
+01167         if (p != 0)
+01168             m_alloc.deallocate(p, n);
+01169     }
+01170 
+01172     void destroy_item(pointer p) {
+01173         m_alloc.destroy(p);
+01174 #if BOOST_CB_ENABLE_DEBUG
+01175         invalidate_iterators(is_invalid_condition(p));
+01176         ::memset(p, cb_details::CB_Unitialized, sizeof(value_type));
+01177 #endif
+01178     }
+01179 
+01181     void destroy_content() {
+01182         for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
+01183             destroy_item(m_first);
+01184     }
+01185 
+01187     void destroy() {
+01188         destroy_content();
+01189         deallocate(m_buff, capacity());
+01190 #if BOOST_CB_ENABLE_DEBUG
+01191         invalidate_all_iterators(); // invalidate iterators pointing to end()
+01192         m_buff = 0;
+01193         m_first = 0;
+01194         m_last = 0;
+01195         m_end = 0;
+01196 #endif
+01197     }
+01198 
+01200     template <class InputIterator>
+01201     void assign(InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
+01202         assign((size_type)n, item);
+01203     }
+01204 
+01206     template <class InputIterator>
+01207     void assign(InputIterator first, InputIterator last, std::input_iterator_tag) {
+01208         BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
+01209         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
+01210         do_assign(std::distance(first, last), assign_range<InputIterator>(first, last, m_alloc));
+01211     }
+01212 
+01214     template <class Functor>
+01215     void do_assign(size_type n, const Functor& fnc) {
+01216         if (n > capacity()) {
+01217             pointer buff = allocate(n);
+01218             BOOST_CB_TRY
+01219             fnc(buff);
+01220             BOOST_CB_UNWIND(deallocate(buff, n))
+01221             destroy();
+01222             m_buff = buff;
+01223             m_end = m_buff + n;
+01224         } else {
+01225             destroy_content();
+01226             BOOST_CB_TRY
+01227             fnc(m_buff);
+01228             BOOST_CB_UNWIND(m_size = 0)
+01229         }
+01230         m_size = n;
+01231         m_first = m_buff;
+01232         m_last = add(m_buff, size());
+01233     }
+01234 
+01236     template <class InputIterator>
+01237     void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
+01238         insert(pos, (size_type)n, item);
+01239     }
+01240 
+01242     template <class InputIterator>
+01243     void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
+01244         BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
+01245         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
+01246         difference_type n = std::distance(first, last);
+01247         if (n == 0)
+01248             return;
+01249         difference_type copy = capacity() - (end() - pos);
+01250         if (copy == 0)
+01251             return;
+01252         if (n > copy) {
+01253             std::advance(first, n - copy);
+01254             n = copy;
+01255         }
+01256         insert_n_item(pos, n, iterator_wrapper<InputIterator>(first));
+01257     }
+01258 
+01260     template <class Wrapper>
+01261     void insert_n_item(iterator pos, size_type n, const Wrapper& wrapper) {
+01262         size_type construct = capacity() - size();
+01263         if (construct > n)
+01264             construct = n;
+01265         if (pos.m_it == 0) {
+01266             size_type ii = 0;
+01267             pointer p = m_last;
+01268             BOOST_CB_TRY
+01269             for (; ii < construct; ++ii, increment(p))
+01270                 m_alloc.construct(p, *wrapper.get_reference());
+01271             for (;ii < n; ++ii, increment(p))
+01272                 replace(p, *wrapper.get_reference());
+01273             BOOST_CB_UNWIND(
+01274                 size_type constructed = std::min(ii, construct);
+01275                 m_last = add(m_last, constructed);
+01276                 m_size += constructed;
+01277                 if (ii >= construct)
+01278                     tidy(p);
+01279             )
+01280         } else {
+01281             pointer src = m_last;
+01282             pointer dest = add(m_last, n - 1);
+01283             size_type ii = 0;
+01284             BOOST_CB_TRY
+01285             while (src != pos.m_it) {
+01286                 decrement(src);
+01287                 create_or_replace(dest, *src);
+01288                 decrement(dest);
+01289             }
+01290             for (dest = pos.m_it; ii < n; ++ii, increment(dest))
+01291                 create_or_replace(dest, *wrapper.get_reference());
+01292             BOOST_CB_UNWIND(
+01293                 for (pointer p1 = m_last, p2 = add(m_last, n - 1); p1 != src; decrement(p2)) {
+01294                     decrement(p1);
+01295                     destroy_created(p2);
+01296                 }
+01297                 for (n = 0, src = pos.m_it; n < ii; ++n, increment(src))
+01298                     destroy_created(src);
+01299                 if (!is_uninitialized(dest))
+01300                     tidy(dest);
+01301             )
+01302         }
+01303         m_last = add(m_last, n);
+01304         m_first = add(m_first, n - construct);
+01305         m_size += construct;
+01306     }
+01307 
+01309     template <class InputIterator>
+01310     void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) {
+01311         rinsert(pos, (size_type)n, item);
+01312     }
+01313 
+01315     template <class InputIterator>
+01316     void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) {
+01317         BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type);
+01318         BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
+01319         rinsert_n_item(pos, std::distance(first, last), iterator_wrapper<InputIterator>(first));
+01320     }
+01321 
+01323     template <class Wrapper>
+01324     void rinsert_n_item(iterator pos, size_type n, const Wrapper& wrapper) {
+01325         if (n == 0)
+01326             return;
+01327         size_type copy = capacity() - (pos - begin());
+01328         if (copy == 0)
+01329             return;
+01330         if (n > copy)
+01331             n = copy;
+01332         size_type construct = capacity() - size();
+01333         if (construct > n)
+01334             construct = n;
+01335         if (pos == begin()) {
+01336             pointer p = sub(map_pointer(pos.m_it), n);
+01337             size_type ii = n;
+01338             BOOST_CB_TRY
+01339             for (;ii > construct; --ii, increment(p))
+01340                 replace(p, *wrapper.get_reference());
+01341             for (; ii > 0; --ii, increment(p))
+01342                 m_alloc.construct(p, *wrapper.get_reference());
+01343             BOOST_CB_UNWIND(
+01344                 size_type unwind = ii < construct ? construct - ii : 0;
+01345                 pointer tmp = sub(map_pointer(pos.m_it), construct);
+01346                 for (n = 0; n < unwind; ++n, increment(tmp))
+01347                     destroy_item(tmp);
+01348                 if (ii > construct)
+01349                     tidy(p);
+01350             )
+01351         } else {
+01352             pointer src = m_first;
+01353             pointer dest = sub(m_first, n);
+01354             pointer p = map_pointer(pos.m_it);
+01355             size_type ii = 0;
+01356             BOOST_CB_TRY
+01357             while (src != p) {
+01358                 create_or_replace(dest, *src);
+01359                 increment(src);
+01360                 increment(dest);
+01361             }
+01362             dest = sub(p, n);
+01363             for (; ii < n; ++ii, increment(dest))
+01364                 create_or_replace(dest, *wrapper.get_reference());
+01365             BOOST_CB_UNWIND(
+01366                 for (pointer p1 = m_first, p2 = sub(m_first, n); p1 != src; increment(p1), increment(p2))
+01367                     destroy_created(p2);
+01368                 p = sub(p, n);
+01369                 for (n = 0; n < ii; ++n, increment(p))
+01370                     destroy_created(p);
+01371                 if (!is_uninitialized(dest))
+01372                     tidy(dest);
+01373             )
+01374         }
+01375         m_first = sub(m_first, n);
+01376         m_last = sub(m_last, n - construct);
+01377         m_size += construct;
+01378     }
+01379 };
+01380 
+01381 // Non-member functions
+01382 
+01384 template <class T, class Alloc>
+01385 inline bool operator == (const circular_buffer<T, Alloc>& lhs,
+01386                          const circular_buffer<T, Alloc>& rhs) {
+01387     return lhs.size() == rhs.size() &&
+01388         std::equal(lhs.begin(), lhs.end(), rhs.begin());
+01389 }
+01390 
+01392 template <class T, class Alloc>
+01393 inline bool operator < (const circular_buffer<T, Alloc>& lhs,
+01394                         const circular_buffer<T, Alloc>& rhs) {
+01395     return std::lexicographical_compare(
+01396         lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+01397 }
+01398 
+01399 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
+01400 
+01402 template <class T, class Alloc>
+01403 inline bool operator != (const circular_buffer<T, Alloc>& lhs,
+01404                          const circular_buffer<T, Alloc>& rhs) {
+01405     return !(lhs == rhs);
+01406 }
+01407 
+01409 template <class T, class Alloc>
+01410 inline bool operator > (const circular_buffer<T, Alloc>& lhs,
+01411                         const circular_buffer<T, Alloc>& rhs) {
+01412     return rhs < lhs;
+01413 }
+01414 
+01416 template <class T, class Alloc>
+01417 inline bool operator <= (const circular_buffer<T, Alloc>& lhs,
+01418                          const circular_buffer<T, Alloc>& rhs) {
+01419     return !(rhs < lhs);
+01420 }
+01421 
+01423 template <class T, class Alloc>
+01424 inline bool operator >= (const circular_buffer<T, Alloc>& lhs,
+01425                          const circular_buffer<T, Alloc>& rhs) {
+01426     return !(lhs < rhs);
+01427 }
+01428 
+01430 template <class T, class Alloc>
+01431 inline void swap(circular_buffer<T, Alloc>& lhs, circular_buffer<T, Alloc>& rhs) {
+01432     lhs.swap(rhs);
+01433 }
+01434 
+01435 #endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
+01436 
+01437 } // namespace boost
+01438 
+01439 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
+

+ + + + + + + + + diff --git a/doc/srcdoc/classboost_1_1circular__buffer-members.html b/doc/srcdoc/classboost_1_1circular__buffer-members.html new file mode 100644 index 0000000..0fa0191 --- /dev/null +++ b/doc/srcdoc/classboost_1_1circular__buffer-members.html @@ -0,0 +1,98 @@ + + + + + Member List + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

boost::circular_buffer< T, Alloc > Member List

This is the complete list of members for boost::circular_buffer< T, Alloc >, including all inherited members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedefboost::circular_buffer< T, Alloc >
assign(size_type n, param_value_type item)boost::circular_buffer< T, Alloc > [inline]
assign(InputIterator first, InputIterator last)boost::circular_buffer< T, Alloc > [inline]
at(size_type index)boost::circular_buffer< T, Alloc > [inline]
at(size_type index) const boost::circular_buffer< T, Alloc > [inline]
back()boost::circular_buffer< T, Alloc > [inline]
back() const boost::circular_buffer< T, Alloc > [inline]
begin()boost::circular_buffer< T, Alloc > [inline]
begin() const boost::circular_buffer< T, Alloc > [inline]
capacity() const boost::circular_buffer< T, Alloc > [inline]
circular_buffer(size_type capacity, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline, explicit]
circular_buffer(size_type capacity, param_value_type item, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline]
circular_buffer(const circular_buffer< T, Alloc > &cb)boost::circular_buffer< T, Alloc > [inline]
circular_buffer(size_type capacity, InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline]
clear()boost::circular_buffer< T, Alloc > [inline]
const_iterator typedefboost::circular_buffer< T, Alloc >
const_pointer typedefboost::circular_buffer< T, Alloc >
const_reference typedefboost::circular_buffer< T, Alloc >
const_reverse_iterator typedefboost::circular_buffer< T, Alloc >
data()boost::circular_buffer< T, Alloc > [inline]
difference_type typedefboost::circular_buffer< T, Alloc >
empty() const boost::circular_buffer< T, Alloc > [inline]
end()boost::circular_buffer< T, Alloc > [inline]
end() const boost::circular_buffer< T, Alloc > [inline]
erase(iterator pos)boost::circular_buffer< T, Alloc > [inline]
erase(iterator first, iterator last)boost::circular_buffer< T, Alloc > [inline]
front()boost::circular_buffer< T, Alloc > [inline]
front() const boost::circular_buffer< T, Alloc > [inline]
full() const boost::circular_buffer< T, Alloc > [inline]
get_allocator() const boost::circular_buffer< T, Alloc > [inline]
get_allocator()boost::circular_buffer< T, Alloc > [inline]
insert(iterator pos, param_value_type item)boost::circular_buffer< T, Alloc > [inline]
insert(iterator pos)boost::circular_buffer< T, Alloc > [inline]
insert(iterator pos, size_type n, param_value_type item)boost::circular_buffer< T, Alloc > [inline]
insert(iterator pos, InputIterator first, InputIterator last)boost::circular_buffer< T, Alloc > [inline]
iterator typedefboost::circular_buffer< T, Alloc >
max_size() const boost::circular_buffer< T, Alloc > [inline]
operator=(const circular_buffer< T, Alloc > &cb)boost::circular_buffer< T, Alloc > [inline]
operator[](size_type index)boost::circular_buffer< T, Alloc > [inline]
operator[](size_type index) const boost::circular_buffer< T, Alloc > [inline]
pointer typedefboost::circular_buffer< T, Alloc >
pop_back()boost::circular_buffer< T, Alloc > [inline]
pop_front()boost::circular_buffer< T, Alloc > [inline]
push_back(param_value_type item)boost::circular_buffer< T, Alloc > [inline]
push_back()boost::circular_buffer< T, Alloc > [inline]
push_front(param_value_type item)boost::circular_buffer< T, Alloc > [inline]
push_front()boost::circular_buffer< T, Alloc > [inline]
rbegin()boost::circular_buffer< T, Alloc > [inline]
rbegin() const boost::circular_buffer< T, Alloc > [inline]
reference typedefboost::circular_buffer< T, Alloc >
rend()boost::circular_buffer< T, Alloc > [inline]
rend() const boost::circular_buffer< T, Alloc > [inline]
resize(size_type new_size, param_value_type item=T(), bool remove_front=true)boost::circular_buffer< T, Alloc > [inline]
reverse_iterator typedefboost::circular_buffer< T, Alloc >
rinsert(iterator pos, param_value_type item)boost::circular_buffer< T, Alloc > [inline]
rinsert(iterator pos)boost::circular_buffer< T, Alloc > [inline]
rinsert(iterator pos, size_type n, param_value_type item)boost::circular_buffer< T, Alloc > [inline]
rinsert(iterator pos, InputIterator first, InputIterator last)boost::circular_buffer< T, Alloc > [inline]
set_capacity(size_type new_capacity, bool remove_front=true)boost::circular_buffer< T, Alloc > [inline]
size() const boost::circular_buffer< T, Alloc > [inline]
size_type typedefboost::circular_buffer< T, Alloc >
swap(circular_buffer &cb)boost::circular_buffer< T, Alloc > [inline]
value_type typedefboost::circular_buffer< T, Alloc >
~circular_buffer()boost::circular_buffer< T, Alloc > [inline]

+ + + + + + + + + diff --git a/doc/srcdoc/classboost_1_1circular__buffer.html b/doc/srcdoc/classboost_1_1circular__buffer.html new file mode 100644 index 0000000..79602d2 --- /dev/null +++ b/doc/srcdoc/classboost_1_1circular__buffer.html @@ -0,0 +1,2938 @@ + + + + + Templateboost::circular_buffer< T, Alloc > class Reference + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

boost::circular_buffer< T, Alloc > Class Template Reference

Circular buffer - a STL compliant container. +More... +

+#include <base.hpp> +

+Inherits cb_iterator_registry. +

+Inherited by boost::circular_buffer_space_optimized< T, Alloc > [private]. +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

typedef Alloc::value_type value_type
 The type of the elements stored in the circular buffer.

typedef Alloc::pointer pointer
 Pointer to the element.

typedef Alloc::const_pointer const_pointer
 Const pointer to the element.

typedef Alloc::reference reference
 Reference to the element.

typedef Alloc::const_reference const_reference
 Const reference to the element.

typedef Alloc::difference_type difference_type
 Distance type.

typedef Alloc::size_type size_type
 Size type.

typedef Alloc allocator_type
 The type of the allocator used in the circular buffer.

typedef cb_details::cb_iterator<
+ circular_buffer< T, Alloc >,
+ cb_details::cb_const_traits<
+ Alloc > > 
const_iterator
 Const (random access) iterator used to iterate through a circular buffer.

typedef cb_details::cb_iterator<
+ circular_buffer< T, Alloc >,
+ cb_details::cb_nonconst_traits<
+ Alloc > > 
iterator
 Iterator (random access) used to iterate through a circular buffer.

typedef reverse_iterator<
+ const_iterator
const_reverse_iterator
 Const iterator used to iterate backwards through a circular buffer.

typedef reverse_iterator<
+ iterator
reverse_iterator
 Iterator used to iterate backwards through a circular buffer.


Public Member Functions

allocator_type get_allocator () const
 Return the allocator.

allocator_typeget_allocator ()
 Return the allocator.

iterator begin ()
 Return an iterator pointing to the beginning of the circular buffer.

iterator end ()
 Return an iterator pointing to the end of the circular buffer.

const_iterator begin () const
 Return a const iterator pointing to the beginning of the circular buffer.

const_iterator end () const
 Return a const iterator pointing to the end of the circular buffer.

reverse_iterator rbegin ()
 Return a reverse iterator pointing to the beginning of the reversed circular buffer.

reverse_iterator rend ()
 Return a reverse iterator pointing to the end of the reversed circular buffer.

const_reverse_iterator rbegin () const
 Return a const reverse iterator pointing to the beginning of the reversed circular buffer.

const_reverse_iterator rend () const
 Return a const reverse iterator pointing to the end of the reversed circular buffer.

reference operator[] (size_type index)
 Return the element at the index position.

return_value_type operator[] (size_type index) const
 Return the element at the index position.

reference at (size_type index)
 Return the element at the index position.

return_value_type at (size_type index) const
 Return the element at the index position.

reference front ()
 Return the first (leftmost) element.

reference back ()
 Return the last (rightmost) element.

return_value_type front () const
 Return the first (leftmost) element.

return_value_type back () const
 Return the last (rightmost) element.

pointer data ()
 Return pointer to data stored in the circular buffer as a continuous array of values.

size_type size () const
 Return the number of elements currently stored in the circular buffer.

size_type max_size () const
 Return the largest possible size (or capacity) of the circular buffer.

bool empty () const
 Is the circular buffer empty?

bool full () const
 Is the circular buffer full?

size_type capacity () const
 Return the capacity of the circular buffer.

void set_capacity (size_type new_capacity, bool remove_front=true)
 Change the capacity of the circular buffer.

void resize (size_type new_size, param_value_type item=T(), bool remove_front=true)
 Change the size of the circular buffer.

 circular_buffer (size_type capacity, const allocator_type &alloc=allocator_type())
 Create an empty circular buffer with a given capacity.

 circular_buffer (size_type capacity, param_value_type item, const allocator_type &alloc=allocator_type())
 Create a full circular buffer with a given capacity and filled with copies of item.

 circular_buffer (const circular_buffer< T, Alloc > &cb)
 Copy constructor.

template<class InputIterator>  circular_buffer (size_type capacity, InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())
 Create a circular buffer with a copy of a range.

 ~circular_buffer ()
 Destructor.

circular_buffer< T, Alloc > & operator= (const circular_buffer< T, Alloc > &cb)
 Assignment operator.

void assign (size_type n, param_value_type item)
 Assign n items into the circular buffer.

template<class InputIterator> void assign (InputIterator first, InputIterator last)
 Assign a copy of range.

void swap (circular_buffer &cb)
 Swap the contents of two circular buffers.

void push_back (param_value_type item)
 Insert a new element at the end.

void push_back ()
 Insert a new element with the default value at the end.

void push_front (param_value_type item)
 Insert a new element at the start.

void push_front ()
 Insert a new element with the default value at the start.

void pop_back ()
 Remove the last (rightmost) element.

void pop_front ()
 Remove the first (leftmost) element.

iterator insert (iterator pos, param_value_type item)
 Insert the item before the given position.

iterator insert (iterator pos)
 Insert a new element with the default value before the given position.

void insert (iterator pos, size_type n, param_value_type item)
 Insert n copies of the item before the given position.

template<class InputIterator> void insert (iterator pos, InputIterator first, InputIterator last)
 Insert the range [first, last) before the given position.

iterator rinsert (iterator pos, param_value_type item)
 Insert an item before the given position.

iterator rinsert (iterator pos)
 Insert a new element with the default value before the given position.

void rinsert (iterator pos, size_type n, param_value_type item)
 Insert n copies of the item before the given position.

template<class InputIterator> void rinsert (iterator pos, InputIterator first, InputIterator last)
 Insert the range [first, last) before the given position.

iterator erase (iterator pos)
 Erase the element at the given position.

iterator erase (iterator first, iterator last)
 Erase the range [first, last).

void clear ()
 Erase all the stored elements.

+


Detailed Description

+

template<class T, class Alloc>
+ class boost::circular_buffer< T, Alloc >

+ +Circular buffer - a STL compliant container. +

+

Parameters:
+ + + +
T The type of the elements stored in the circular buffer.
Alloc The allocator type used for all internal memory management.
+
+
Author:
Jan Gaspar
+
Version:
3.6
+
Date:
2004
+For more information how to use the circular buffer see the documentation. +

+


Member Typedef Documentation

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc boost::circular_buffer< T, Alloc >::allocator_type +
+
+ + + + + +
+   + + +

+The type of the allocator used in the circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_const_traits<Alloc> > boost::circular_buffer< T, Alloc >::const_iterator +
+
+ + + + + +
+   + + +

+Const (random access) iterator used to iterate through a circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::const_pointer boost::circular_buffer< T, Alloc >::const_pointer +
+
+ + + + + +
+   + + +

+Const pointer to the element. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::const_reference boost::circular_buffer< T, Alloc >::const_reference +
+
+ + + + + +
+   + + +

+Const reference to the element. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef reverse_iterator<const_iterator> boost::circular_buffer< T, Alloc >::const_reverse_iterator +
+
+ + + + + +
+   + + +

+Const iterator used to iterate backwards through a circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::difference_type boost::circular_buffer< T, Alloc >::difference_type +
+
+ + + + + +
+   + + +

+Distance type. +

+A signed integral type used to represent the distance between two iterators. +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef cb_details::cb_iterator< circular_buffer<T, Alloc>, cb_details::cb_nonconst_traits<Alloc> > boost::circular_buffer< T, Alloc >::iterator +
+
+ + + + + +
+   + + +

+Iterator (random access) used to iterate through a circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::pointer boost::circular_buffer< T, Alloc >::pointer +
+
+ + + + + +
+   + + +

+Pointer to the element. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::reference boost::circular_buffer< T, Alloc >::reference +
+
+ + + + + +
+   + + +

+Reference to the element. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef reverse_iterator<iterator> boost::circular_buffer< T, Alloc >::reverse_iterator +
+
+ + + + + +
+   + + +

+Iterator used to iterate backwards through a circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::size_type boost::circular_buffer< T, Alloc >::size_type +
+
+ + + + + +
+   + + +

+Size type. +

+An unsigned integral type that can represent any nonnegative value of the container's distance type. +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef Alloc::value_type boost::circular_buffer< T, Alloc >::value_type +
+
+ + + + + +
+   + + +

+The type of the elements stored in the circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+


Constructor & Destructor Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer< T, Alloc >::circular_buffer size_type  capacity,
const allocator_type alloc = allocator_type()
[inline, explicit]
+
+ + + + + +
+   + + +

+Create an empty circular buffer with a given capacity. +

+

Postcondition:
(*this).capacity() == capacity && (*this).size == 0
+
Exceptions:
+ + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
+
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer< T, Alloc >::circular_buffer size_type  capacity,
param_value_type  item,
const allocator_type alloc = allocator_type()
[inline]
+
+ + + + + +
+   + + +

+Create a full circular buffer with a given capacity and filled with copies of item. +

+

Postcondition:
(*this).size() == capacity && (*this)[0] == (*this)[1] == ... == (*this).back() == item
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer< T, Alloc >::circular_buffer const circular_buffer< T, Alloc > &  cb  )  [inline]
+
+ + + + + +
+   + + +

+Copy constructor. +

+

Postcondition:
*this == cb
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
boost::circular_buffer< T, Alloc >::circular_buffer size_type  capacity,
InputIterator  first,
InputIterator  last,
const allocator_type alloc = allocator_type()
[inline]
+
+ + + + + +
+   + + +

+Create a circular buffer with a copy of a range. +

+

Precondition:
Valid range [first, last).
+
Postcondition:
(*this).capacity() == capacity
+ If the number of items to copy from the range [first, last) is greater than the specified capacity then only elements from the range [last - capacity, last) will be copied.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer< T, Alloc >::~circular_buffer  )  [inline]
+
+ + + + + +
+   + + +

+Destructor. +

+

+


Member Function Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer< T, Alloc >::assign InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+Assign a copy of range. +

+

Precondition:
Valid range [first, last).
+
Postcondition:
(*this).size() == std::distance(first, last)
+ If the number of items to be assigned exceeds the capacity of the circular buffer the capacity is set to that number otherwise is stays unchanged.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::assign size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+Assign n items into the circular buffer. +

+

Postcondition:
(*this).size() == n && (*this)[0] == (*this)[1] == ... == (*this).back() == item
+ If the number of items to be assigned exceeds the capacity of the circular buffer the capacity is increased to n otherwise it stays unchanged.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
return_value_type boost::circular_buffer< T, Alloc >::at size_type  index  )  const [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Exceptions:
+ + +
std::out_of_range thrown when the index is invalid.
+
+
+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
reference boost::circular_buffer< T, Alloc >::at size_type  index  )  [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Exceptions:
+ + +
std::out_of_range thrown when the index is invalid.
+
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
return_value_type boost::circular_buffer< T, Alloc >::back  )  const [inline]
+
+ + + + + +
+   + + +

+Return the last (rightmost) element. +

+

Precondition:
!*(this).empty()
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
reference boost::circular_buffer< T, Alloc >::back  )  [inline]
+
+ + + + + +
+   + + +

+Return the last (rightmost) element. +

+

Precondition:
!*(this).empty()
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
const_iterator boost::circular_buffer< T, Alloc >::begin  )  const [inline]
+
+ + + + + +
+   + + +

+Return a const iterator pointing to the beginning of the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::begin  )  [inline]
+
+ + + + + +
+   + + +

+Return an iterator pointing to the beginning of the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer< T, Alloc >::capacity  )  const [inline]
+
+ + + + + +
+   + + +

+Return the capacity of the circular buffer. +

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::clear  )  [inline]
+
+ + + + + +
+   + + +

+Erase all the stored elements. +

+

Postcondition:
(*this).size() == 0
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
pointer boost::circular_buffer< T, Alloc >::data  )  [inline]
+
+ + + + + +
+   + + +

+Return pointer to data stored in the circular buffer as a continuous array of values. +

+This method can be useful e.g. when passing the stored data into the legacy C API.

Postcondition:
&(*this)[0] < &(*this)[1] < ... < &(*this).back()
+
Returns:
0 if empty.
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
bool boost::circular_buffer< T, Alloc >::empty  )  const [inline]
+
+ + + + + +
+   + + +

+Is the circular buffer empty? +

+

Returns:
true if there are no elements stored in the circular buffer.

+false otherwise.

+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
const_iterator boost::circular_buffer< T, Alloc >::end  )  const [inline]
+
+ + + + + +
+   + + +

+Return a const iterator pointing to the end of the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::end  )  [inline]
+
+ + + + + +
+   + + +

+Return an iterator pointing to the end of the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::erase iterator  first,
iterator  last
[inline]
+
+ + + + + +
+   + + +

+Erase the range [first, last). +

+

Precondition:
Valid range [first, last).

+size_type old_size = (*this).size()

+
Postcondition:
(*this).size() == old_size - std::distance(first, last)
+ Removes the elements from the range [first, last).
+
Returns:
iterator to the first element remaining beyond the removed element or (*this).end() if no such element exists.
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::erase iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+Erase the element at the given position. +

+

Precondition:
Valid pos iterator.

+size_type old_size = (*this).size()

+
Postcondition:
(*this).size() == old_size - 1
+ Removes an element at the position pos.
+
Returns:
iterator to the first element remaining beyond the removed element or (*this).end() if no such element exists.
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
return_value_type boost::circular_buffer< T, Alloc >::front  )  const [inline]
+
+ + + + + +
+   + + +

+Return the first (leftmost) element. +

+

Precondition:
!*(this).empty()
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
reference boost::circular_buffer< T, Alloc >::front  )  [inline]
+
+ + + + + +
+   + + +

+Return the first (leftmost) element. +

+

Precondition:
!*(this).empty()
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
bool boost::circular_buffer< T, Alloc >::full  )  const [inline]
+
+ + + + + +
+   + + +

+Is the circular buffer full? +

+

Returns:
true if the number of elements stored in the circular buffer equals the capacity of the circular buffer.

+false otherwise.

+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
allocator_type& boost::circular_buffer< T, Alloc >::get_allocator  )  [inline]
+
+ + + + + +
+   + + +

+Return the allocator. +

+

Note:
This method was added in order to optimize obtaining of the allocator with a state, although use of stateful allocators in STL is discouraged.
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
allocator_type boost::circular_buffer< T, Alloc >::get_allocator  )  const [inline]
+
+ + + + + +
+   + + +

+Return the allocator. +

+

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer< T, Alloc >::insert iterator  pos,
InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+Insert the range [first, last) before the given position. +

+

Precondition:
Valid pos iterator and valid range [first, last).
+
Postcondition:
This operation preserves the capacity of the circular buffer. If the insertion would result in exceeding the capacity of the circular buffer then the necessary number of elements from the beginning (left) of the circular buffer will be removed or not the whole range will be inserted or both. In case the whole range cannot be inserted it will be inserted just some elements from the end (right) of the range (see the example).
+ Example:
+ array to insert: int array[] = { 5, 6, 7, 8, 9 };
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, array, array + 5);
+ (If the operation won't preserve capacity, the buffer would look like this |1|2|5|6|7|8|9|3|4|)
+ RESULTING circular buffer |6|7|8|9|3|4| - capacity: 6, size: 6
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::insert iterator  pos,
size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+Insert n copies of the item before the given position. +

+

Precondition:
Valid pos iterator.
+
Postcondition:
This operation preserves the capacity of the circular buffer. If the insertion would result in exceeding the capacity of the circular buffer then the necessary number of elements from the beginning (left) of the circular buffer will be removed or not all n elements will be inserted or both.
+ Example:
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, (size_t)5, 6);
+ (If the operation won't preserve capacity, the buffer would look like this |1|2|6|6|6|6|6|3|4|)
+ RESULTING circular buffer |6|6|6|6|3|4| - capacity: 6, size: 6
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::insert iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element with the default value before the given position. +

+

Postcondition:
value_type() will be inserted at the position pos.
+ If the circular buffer is full, the first (leftmost) element will be removed.
+
Returns:
iterator to the inserted element.
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::insert iterator  pos,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+Insert the item before the given position. +

+

Precondition:
Valid pos iterator.
+
Postcondition:
The item will be inserted at the position pos.
+ If the circular buffer is full, the first (leftmost) element will be removed.
+
Returns:
iterator to the inserted element.
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer< T, Alloc >::max_size  )  const [inline]
+
+ + + + + +
+   + + +

+Return the largest possible size (or capacity) of the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
circular_buffer<T, Alloc>& boost::circular_buffer< T, Alloc >::operator= const circular_buffer< T, Alloc > &  cb  )  [inline]
+
+ + + + + +
+   + + +

+Assignment operator. +

+

Postcondition:
*this == cb
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+
+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
return_value_type boost::circular_buffer< T, Alloc >::operator[] size_type  index  )  const [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Precondition:
*(this).size() > index
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
reference boost::circular_buffer< T, Alloc >::operator[] size_type  index  )  [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Precondition:
*(this).size() > index
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::pop_back  )  [inline]
+
+ + + + + +
+   + + +

+Remove the last (rightmost) element. +

+

Precondition:
!*(this).empty()

+iterator it = ((*this).end() - 1)

+
Postcondition:
((*this).end() - 1) != it
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::pop_front  )  [inline]
+
+ + + + + +
+   + + +

+Remove the first (leftmost) element. +

+

Precondition:
!*(this).empty()

+iterator it = (*this).begin()

+
Postcondition:
(*this).begin() != it
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::push_back  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element with the default value at the end. +

+

Postcondition:
(*this).back() == value_type()
+ If the circular buffer is full, the first (leftmost) element will be removed.
+
Exceptions:
+ + +
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::push_back param_value_type  item  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element at the end. +

+

Postcondition:
(*this).back() == item
+ If the circular buffer is full, the first (leftmost) element will be removed.
+
Exceptions:
+ + +
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::push_front  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element with the default value at the start. +

+

Postcondition:
(*this).front() == value_type()
+ If the circular buffer is full, the last (rightmost) element will be removed.
+
Exceptions:
+ + +
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::push_front param_value_type  item  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element at the start. +

+

Postcondition:
(*this).front() == item
+ If the circular buffer is full, the last (rightmost) element will be removed.
+
Exceptions:
+ + +
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
const_reverse_iterator boost::circular_buffer< T, Alloc >::rbegin  )  const [inline]
+
+ + + + + +
+   + + +

+Return a const reverse iterator pointing to the beginning of the reversed circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
reverse_iterator boost::circular_buffer< T, Alloc >::rbegin  )  [inline]
+
+ + + + + +
+   + + +

+Return a reverse iterator pointing to the beginning of the reversed circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
const_reverse_iterator boost::circular_buffer< T, Alloc >::rend  )  const [inline]
+
+ + + + + +
+   + + +

+Return a const reverse iterator pointing to the end of the reversed circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
reverse_iterator boost::circular_buffer< T, Alloc >::rend  )  [inline]
+
+ + + + + +
+   + + +

+Return a reverse iterator pointing to the end of the reversed circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::resize size_type  new_size,
param_value_type  item = T(),
bool  remove_front = true
[inline]
+
+ + + + + +
+   + + +

+Change the size of the circular buffer. +

+

Parameters:
+ + + + +
new_size The new size.
item See the postcondition.
remove_front This parameter plays its role only if the current number of elements stored in the circular buffer is greater than the desired new capacity. If set to true then the first (leftmost) elements will be removed. If set to false then the last (leftmost) elements will be removed.
+
+
Postcondition:
(*this).size() == new_size
+ If the new size is greater than the current size, the rest of the circular buffer is filled with copies of item. In case the resulting size exceeds the current capacity the capacity is set to new_size. If the new size is lower than the current size then ((*this).size() - new_size) elements will be removed according to the remove_front parameter.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer< T, Alloc >::rinsert iterator  pos,
InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+Insert the range [first, last) before the given position. +

+

Precondition:
Valid pos iterator and valid range [first, last).
+
Postcondition:
This operation preserves the capacity of the circular buffer. If the insertion would result in exceeding the capacity of the circular buffer then the necessary number of elements from the end (right) of the circular buffer will be removed or not the whole range will be inserted or both. In case the whole range cannot be inserted it will be inserted just some elements from the beginning (left) of the range (see the example).
+ Example:
+ array to insert: int array[] = { 5, 6, 7, 8, 9 };
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, array, array + 5);
+ (If the operation won't preserve capacity, the buffer would look like this |1|2|5|6|7|8|9|3|4|)
+ RESULTING circular buffer |1|2|5|6|7|8| - capacity: 6, size: 6
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::rinsert iterator  pos,
size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+Insert n copies of the item before the given position. +

+

Precondition:
Valid pos iterator.
+
Postcondition:
This operation preserves the capacity of the circular buffer. If the insertion would result in exceeding the capacity of the circular buffer then the necessary number of elements from the end (right) of the circular buffer will be removed or not all n elements will be inserted or both.
+ Example:
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, (size_t)5, 6);
+ (If the operation won't preserve capacity, the buffer would look like this |1|2|6|6|6|6|6|3|4|)
+ RESULTING circular buffer |1|2|6|6|6|6| - capacity: 6, size: 6
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::rinsert iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+Insert a new element with the default value before the given position. +

+

Postcondition:
value_type() will be inserted at the position pos.
+ If the circular buffer is full, the last (rightmost) element will be removed.
+
Returns:
iterator to the inserted element.
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer< T, Alloc >::rinsert iterator  pos,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+Insert an item before the given position. +

+

Precondition:
Valid pos iterator.
+
Postcondition:
The item will be inserted at the position pos.
+ If the circular buffer is full, the last element (rightmost) will be removed.
+
Returns:
iterator to the inserted element.
+
Exceptions:
+ + + +
Whatever T::T(const T&) throws.
Whatever T::operator = (const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::set_capacity size_type  new_capacity,
bool  remove_front = true
[inline]
+
+ + + + + +
+   + + +

+Change the capacity of the circular buffer. +

+

Parameters:
+ + + +
new_capacity The new capacity.
remove_front This parameter plays its role only if the current number of elements stored in the circular buffer is greater than the desired new capacity. If set to true then the first (leftmost) elements will be removed. If set to false then the last (leftmost) elements will be removed.
+
+
Postcondition:
(*this).capacity() == new_capacity
+ If the current number of elements stored in the circular buffer is greater than the desired new capacity then ((*this).size() - new_capacity) elements will be removed according to the remove_front parameter.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
For iterator invalidation see the documentation.
+ +

+Reimplemented in boost::circular_buffer_space_optimized< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer< T, Alloc >::size  )  const [inline]
+
+ + + + + +
+   + + +

+Return the number of elements currently stored in the circular buffer. +

+

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer< T, Alloc >::swap circular_buffer< T, Alloc > &  cb  )  [inline]
+
+ + + + + +
+   + + +

+Swap the contents of two circular buffers. +

+

Postcondition:
this contains elements of cb and vice versa.
+
Note:
For iterator invalidation see the documentation.
+
+


+ + + + + + + + + diff --git a/doc/srcdoc/classboost_1_1circular__buffer__space__optimized-members.html b/doc/srcdoc/classboost_1_1circular__buffer__space__optimized-members.html new file mode 100644 index 0000000..4b37cec --- /dev/null +++ b/doc/srcdoc/classboost_1_1circular__buffer__space__optimized-members.html @@ -0,0 +1,105 @@ + + + + + Member List + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

boost::circular_buffer_space_optimized< T, Alloc > Member List

This is the complete list of members for boost::circular_buffer_space_optimized< T, Alloc >, including all inherited members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedefboost::circular_buffer_space_optimized< T, Alloc >
assign(size_type n, param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
assign(InputIterator first, InputIterator last)boost::circular_buffer_space_optimized< T, Alloc > [inline]
at(size_type index)boost::circular_buffer< T, Alloc > [inline, private]
at(size_type index) const boost::circular_buffer< T, Alloc > [inline, private]
back()boost::circular_buffer< T, Alloc > [inline, private]
back() const boost::circular_buffer< T, Alloc > [inline, private]
begin()boost::circular_buffer< T, Alloc > [inline, private]
begin() const boost::circular_buffer< T, Alloc > [inline, private]
capacity() const boost::circular_buffer_space_optimized< T, Alloc > [inline]
circular_buffer(size_type capacity, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline, explicit, private]
circular_buffer(size_type capacity, param_value_type item, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline, private]
circular_buffer(const circular_buffer< T, Alloc > &cb)boost::circular_buffer< T, Alloc > [inline, private]
circular_buffer(size_type capacity, InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())boost::circular_buffer< T, Alloc > [inline, private]
circular_buffer_space_optimized(size_type capacity, size_type min_capacity=0, const allocator_type &alloc=allocator_type())boost::circular_buffer_space_optimized< T, Alloc > [inline, explicit]
circular_buffer_space_optimized(size_type capacity, size_type min_capacity, param_value_type item, const allocator_type &alloc=allocator_type())boost::circular_buffer_space_optimized< T, Alloc > [inline]
circular_buffer_space_optimized(size_type capacity, size_type min_capacity, InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())boost::circular_buffer_space_optimized< T, Alloc > [inline]
clear()boost::circular_buffer_space_optimized< T, Alloc > [inline]
const_iterator typedefboost::circular_buffer_space_optimized< T, Alloc >
const_pointer typedefboost::circular_buffer_space_optimized< T, Alloc >
const_reference typedefboost::circular_buffer_space_optimized< T, Alloc >
const_reverse_iterator typedefboost::circular_buffer_space_optimized< T, Alloc >
data()boost::circular_buffer< T, Alloc > [inline, private]
difference_type typedefboost::circular_buffer_space_optimized< T, Alloc >
empty() const boost::circular_buffer< T, Alloc > [inline, private]
end()boost::circular_buffer< T, Alloc > [inline, private]
end() const boost::circular_buffer< T, Alloc > [inline, private]
erase(iterator pos)boost::circular_buffer_space_optimized< T, Alloc > [inline]
erase(iterator first, iterator last)boost::circular_buffer_space_optimized< T, Alloc > [inline]
front()boost::circular_buffer< T, Alloc > [inline, private]
front() const boost::circular_buffer< T, Alloc > [inline, private]
full() const boost::circular_buffer_space_optimized< T, Alloc > [inline]
get_allocator() const boost::circular_buffer< T, Alloc > [inline, private]
get_allocator()boost::circular_buffer< T, Alloc > [inline, private]
insert(iterator pos, param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
insert(iterator pos)boost::circular_buffer_space_optimized< T, Alloc > [inline]
insert(iterator pos, size_type n, param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
insert(iterator pos, InputIterator first, InputIterator last)boost::circular_buffer_space_optimized< T, Alloc > [inline]
internal_capacity() const boost::circular_buffer_space_optimized< T, Alloc > [inline]
iterator typedefboost::circular_buffer_space_optimized< T, Alloc >
max_size() const boost::circular_buffer< T, Alloc > [inline, private]
min_capacity() const boost::circular_buffer_space_optimized< T, Alloc > [inline]
operator=(const circular_buffer< T, Alloc > &cb)boost::circular_buffer< T, Alloc > [inline, private]
operator[](size_type n)boost::circular_buffer_space_optimized< T, Alloc > [inline]
operator[](size_type n) const boost::circular_buffer_space_optimized< T, Alloc > [inline]
pointer typedefboost::circular_buffer_space_optimized< T, Alloc >
pop_back()boost::circular_buffer_space_optimized< T, Alloc > [inline]
pop_front()boost::circular_buffer_space_optimized< T, Alloc > [inline]
push_back(param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
push_back()boost::circular_buffer_space_optimized< T, Alloc > [inline]
push_front(param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
push_front()boost::circular_buffer_space_optimized< T, Alloc > [inline]
rbegin()boost::circular_buffer< T, Alloc > [inline, private]
rbegin() const boost::circular_buffer< T, Alloc > [inline, private]
reference typedefboost::circular_buffer_space_optimized< T, Alloc >
rend()boost::circular_buffer< T, Alloc > [inline, private]
rend() const boost::circular_buffer< T, Alloc > [inline, private]
resize(size_type new_size, param_value_type item=T(), bool remove_front=true)boost::circular_buffer_space_optimized< T, Alloc > [inline]
reverse_iterator typedefboost::circular_buffer_space_optimized< T, Alloc >
rinsert(iterator pos, param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
rinsert(iterator pos)boost::circular_buffer_space_optimized< T, Alloc > [inline]
rinsert(iterator pos, size_type n, param_value_type item)boost::circular_buffer_space_optimized< T, Alloc > [inline]
rinsert(iterator pos, InputIterator first, InputIterator last)boost::circular_buffer_space_optimized< T, Alloc > [inline]
set_capacity(size_type new_capacity, bool remove_front=true)boost::circular_buffer_space_optimized< T, Alloc > [inline]
set_min_capacity(size_type new_min_capacity)boost::circular_buffer_space_optimized< T, Alloc > [inline]
size() const boost::circular_buffer< T, Alloc > [inline, private]
size_type typedefboost::circular_buffer_space_optimized< T, Alloc >
swap(circular_buffer_space_optimized &cb)boost::circular_buffer_space_optimized< T, Alloc > [inline]
boost::circular_buffer::swap(circular_buffer &cb)boost::circular_buffer< T, Alloc > [inline, private]
value_type typedefboost::circular_buffer_space_optimized< T, Alloc >
~circular_buffer()boost::circular_buffer< T, Alloc > [inline, private]

+ + + + + + + + + diff --git a/doc/srcdoc/classboost_1_1circular__buffer__space__optimized.html b/doc/srcdoc/classboost_1_1circular__buffer__space__optimized.html new file mode 100644 index 0000000..4ea608f --- /dev/null +++ b/doc/srcdoc/classboost_1_1circular__buffer__space__optimized.html @@ -0,0 +1,2015 @@ + + + + + Templateboost::circular_buffer_space_optimized< T, Alloc > class Reference + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

boost::circular_buffer_space_optimized< T, Alloc > Class Template Reference

Space optimized circular buffer container adaptor. +More... +

+#include <adaptor.hpp> +

+Inherits boost::circular_buffer< T, Alloc >< T, Alloc >. +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

typedef circular_buffer< T,
+ Alloc >::value_type 
value_type
 The type of the elements stored in the circular buffer.

typedef circular_buffer< T,
+ Alloc >::pointer 
pointer
 Pointer to the element.

typedef circular_buffer< T,
+ Alloc >::const_pointer 
const_pointer
 Const pointer to the element.

typedef circular_buffer< T,
+ Alloc >::reference 
reference
 Reference to the element.

typedef circular_buffer< T,
+ Alloc >::const_reference 
const_reference
 Const reference to the element.

typedef circular_buffer< T,
+ Alloc >::size_type 
size_type
 Size type.

typedef circular_buffer< T,
+ Alloc >::difference_type 
difference_type
 Distance type.

typedef circular_buffer< T,
+ Alloc >::allocator_type 
allocator_type
 The type of the allocator used in the circular buffer.

typedef circular_buffer< T,
+ Alloc >::const_iterator 
const_iterator
 Const (random access) iterator used to iterate through a circular buffer.

typedef circular_buffer< T,
+ Alloc >::iterator 
iterator
 Iterator (random access) used to iterate through a circular buffer.

typedef circular_buffer< T,
+ Alloc >::const_reverse_iterator 
const_reverse_iterator
 Const iterator used to iterate backwards through a circular buffer.

typedef circular_buffer< T,
+ Alloc >::reverse_iterator 
reverse_iterator
 Iterator used to iterate backwards through a circular buffer.


Public Member Functions

reference operator[] (size_type n)
 Return the element at the index position.

return_value_type operator[] (size_type n) const
 Return the element at the index position.

bool full () const
 See the circular_buffer source documentation.

size_type min_capacity () const
 Return the minimal guaranteed amount of allocated memory.

void set_min_capacity (size_type new_min_capacity)
 Change the minimal guaranteed amount of allocated memory.

size_type capacity () const
 See the circular_buffer source documentation.

size_type internal_capacity () const
 Return the current capacity of the adapted circular buffer.

void set_capacity (size_type new_capacity, bool remove_front=true)
 See the circular_buffer source documentation.

void resize (size_type new_size, param_value_type item=T(), bool remove_front=true)
 See the circular_buffer source documentation.

 circular_buffer_space_optimized (size_type capacity, size_type min_capacity=0, const allocator_type &alloc=allocator_type())
 Create an empty space optimized circular buffer with a given capacity.

 circular_buffer_space_optimized (size_type capacity, size_type min_capacity, param_value_type item, const allocator_type &alloc=allocator_type())
 Create a full space optimized circular buffer filled with copies of item.

template<class InputIterator>  circular_buffer_space_optimized (size_type capacity, size_type min_capacity, InputIterator first, InputIterator last, const allocator_type &alloc=allocator_type())
 Create a space optimized circular buffer with a copy of a range.

void assign (size_type n, param_value_type item)
 See the circular_buffer source documentation.

template<class InputIterator> void assign (InputIterator first, InputIterator last)
 See the circular_buffer source documentation.

void swap (circular_buffer_space_optimized &cb)
 See the circular_buffer source documentation.

void push_back (param_value_type item)
 See the circular_buffer source documentation.

void push_back ()
 See the circular_buffer source documentation.

void push_front (param_value_type item)
 See the circular_buffer source documentation.

void push_front ()
 See the circular_buffer source documentation.

void pop_back ()
 See the circular_buffer source documentation.

void pop_front ()
 See the circular_buffer source documentation.

iterator insert (iterator pos, param_value_type item)
 See the circular_buffer source documentation.

iterator insert (iterator pos)
 See the circular_buffer source documentation.

void insert (iterator pos, size_type n, param_value_type item)
 See the circular_buffer source documentation.

template<class InputIterator> void insert (iterator pos, InputIterator first, InputIterator last)
 See the circular_buffer source documentation.

iterator rinsert (iterator pos, param_value_type item)
 See the circular_buffer source documentation.

iterator rinsert (iterator pos)
 See the circular_buffer source documentation.

void rinsert (iterator pos, size_type n, param_value_type item)
 See the circular_buffer source documentation.

template<class InputIterator> void rinsert (iterator pos, InputIterator first, InputIterator last)
 See the circular_buffer source documentation.

iterator erase (iterator pos)
 See the circular_buffer source documentation.

iterator erase (iterator first, iterator last)
 See the circular_buffer source documentation.

void clear ()
 See the circular_buffer source documentation.

+


Detailed Description

+

template<class T, class Alloc>
+ class boost::circular_buffer_space_optimized< T, Alloc >

+ +Space optimized circular buffer container adaptor. +

+

Parameters:
+ + + +
T The type of the elements stored in the space optimized circular buffer.
Alloc The allocator type used for all internal memory management.
+
+
Author:
Jan Gaspar
+
Version:
1.3
+
Date:
2004
+For more information how to use the space optimized circular buffer see the documentation. +

+


Member Typedef Documentation

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::allocator_type boost::circular_buffer_space_optimized< T, Alloc >::allocator_type +
+
+ + + + + +
+   + + +

+The type of the allocator used in the circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::const_iterator boost::circular_buffer_space_optimized< T, Alloc >::const_iterator +
+
+ + + + + +
+   + + +

+Const (random access) iterator used to iterate through a circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::const_pointer boost::circular_buffer_space_optimized< T, Alloc >::const_pointer +
+
+ + + + + +
+   + + +

+Const pointer to the element. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::const_reference boost::circular_buffer_space_optimized< T, Alloc >::const_reference +
+
+ + + + + +
+   + + +

+Const reference to the element. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::const_reverse_iterator boost::circular_buffer_space_optimized< T, Alloc >::const_reverse_iterator +
+
+ + + + + +
+   + + +

+Const iterator used to iterate backwards through a circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::difference_type boost::circular_buffer_space_optimized< T, Alloc >::difference_type +
+
+ + + + + +
+   + + +

+Distance type. +

+A signed integral type used to represent the distance between two iterators. +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::iterator boost::circular_buffer_space_optimized< T, Alloc >::iterator +
+
+ + + + + +
+   + + +

+Iterator (random access) used to iterate through a circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::pointer boost::circular_buffer_space_optimized< T, Alloc >::pointer +
+
+ + + + + +
+   + + +

+Pointer to the element. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::reference boost::circular_buffer_space_optimized< T, Alloc >::reference +
+
+ + + + + +
+   + + +

+Reference to the element. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::reverse_iterator boost::circular_buffer_space_optimized< T, Alloc >::reverse_iterator +
+
+ + + + + +
+   + + +

+Iterator used to iterate backwards through a circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::size_type boost::circular_buffer_space_optimized< T, Alloc >::size_type +
+
+ + + + + +
+   + + +

+Size type. +

+An unsigned integral type that can represent any nonnegative value of the container's distance type. +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + +
+template<class T, class Alloc>
typedef circular_buffer<T, Alloc>::value_type boost::circular_buffer_space_optimized< T, Alloc >::value_type +
+
+ + + + + +
+   + + +

+The type of the elements stored in the circular buffer. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+


Constructor & Destructor Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer_space_optimized< T, Alloc >::circular_buffer_space_optimized size_type  capacity,
size_type  min_capacity = 0,
const allocator_type alloc = allocator_type()
[inline, explicit]
+
+ + + + + +
+   + + +

+Create an empty space optimized circular buffer with a given capacity. +

+

Parameters:
+ + + + +
capacity The capacity of the buffer.
min_capacity The minimal guaranteed amount of allocated memory. (The metrics of the min_capacity is number of items.)
alloc The allocator.
+
+
Precondition:
capacity >= min_capacity
+
Postcondition:
(*this).capacity() == capacity && (*this).size == 0
+ Allocates memory specified by the min_capacity parameter.
+
Exceptions:
+ + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
+
+
Note:
It is considered as a bug if the precondition is not met (i.e. if capacity < min_capacity) and an assertion will be invoked in the debug mode.
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
boost::circular_buffer_space_optimized< T, Alloc >::circular_buffer_space_optimized size_type  capacity,
size_type  min_capacity,
param_value_type  item,
const allocator_type alloc = allocator_type()
[inline]
+
+ + + + + +
+   + + +

+Create a full space optimized circular buffer filled with copies of item. +

+

Parameters:
+ + + + + +
capacity The capacity of the buffer.
min_capacity The minimal guaranteed amount of allocated memory. (The metrics of the min_capacity is number of items.)
item The item to be filled with.
alloc The allocator.
+
+
Precondition:
capacity >= min_capacity
+
Postcondition:
(*this).size() == capacity && (*this)[0] == (*this)[1] == ... == (*this).back() == item
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
It is considered as a bug if the precondition is not met (i.e. if capacity < min_capacity) and an assertion will be invoked in the debug mode.
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
boost::circular_buffer_space_optimized< T, Alloc >::circular_buffer_space_optimized size_type  capacity,
size_type  min_capacity,
InputIterator  first,
InputIterator  last,
const allocator_type alloc = allocator_type()
[inline]
+
+ + + + + +
+   + + +

+Create a space optimized circular buffer with a copy of a range. +

+

Parameters:
+ + + + + + +
capacity The capacity of the buffer.
min_capacity The minimal guaranteed amount of allocated memory. (The metrics of the min_capacity is number of items.)
first The beginning of the range.
last The end of the range.
alloc The allocator.
+
+
Precondition:
capacity >= min_capacity and valid range [first, last).
+
Postcondition:
(*this).capacity() == capacity
+ Allocates at least as much memory as specified by the min_capacity parameter.
+ If the number of items to copy from the range [first, last) is greater than the specified capacity then only elements from the range [last - capacity, last) will be copied.
+
Exceptions:
+ + + +
An allocation error if memory is exhausted (std::bad_alloc if standard allocator is used).
Whatever T::T(const T&) throws.
+
+
Note:
It is considered as a bug if the precondition is not met (i.e. if capacity < min_capacity) and an assertion will be invoked in the debug mode.
+
+


Member Function Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer_space_optimized< T, Alloc >::assign InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::assign size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer_space_optimized< T, Alloc >::capacity  )  const [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::clear  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::erase iterator  first,
iterator  last
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::erase iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
bool boost::circular_buffer_space_optimized< T, Alloc >::full  )  const [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer_space_optimized< T, Alloc >::insert iterator  pos,
InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::insert iterator  pos,
size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::insert iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::insert iterator  pos,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer_space_optimized< T, Alloc >::internal_capacity  )  const [inline]
+
+ + + + + +
+   + + +

+Return the current capacity of the adapted circular buffer. +

+

Note:
This method is not intended to be used directly by the user. It is defined only for testing purposes.
+
+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
size_type boost::circular_buffer_space_optimized< T, Alloc >::min_capacity  )  const [inline]
+
+ + + + + +
+   + + +

+Return the minimal guaranteed amount of allocated memory. +

+The allocated memory will never drop under this value.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
return_value_type boost::circular_buffer_space_optimized< T, Alloc >::operator[] size_type  n  )  const [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Precondition:
*(this).size() > index
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
reference boost::circular_buffer_space_optimized< T, Alloc >::operator[] size_type  n  )  [inline]
+
+ + + + + +
+   + + +

+Return the element at the index position. +

+

Precondition:
*(this).size() > index
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::pop_back  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::pop_front  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::push_back  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::push_back param_value_type  item  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::push_front  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::push_front param_value_type  item  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::resize size_type  new_size,
param_value_type  item = T(),
bool  remove_front = true
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
+template<class InputIterator>
void boost::circular_buffer_space_optimized< T, Alloc >::rinsert iterator  pos,
InputIterator  first,
InputIterator  last
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::rinsert iterator  pos,
size_type  n,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::rinsert iterator  pos  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
iterator boost::circular_buffer_space_optimized< T, Alloc >::rinsert iterator  pos,
param_value_type  item
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Warning:
The rules for iterator invalidation differ from the original circular_buffer. See the documentation.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::set_capacity size_type  new_capacity,
bool  remove_front = true
[inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

Precondition:
(*this).min_capacity() <= new_capacity
+
Note:
It is considered as a bug if the precondition is not met (i.e. if new_capacity > (*this).min_capacity()) and an assertion will be invoked in the debug mode.
+ +

+Reimplemented from boost::circular_buffer< T, Alloc >.

+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::set_min_capacity size_type  new_min_capacity  )  [inline]
+
+ + + + + +
+   + + +

+Change the minimal guaranteed amount of allocated memory. +

+

Precondition:
(*this).capacity() >= new_min_capacity
+
Postcondition:
(*this).min_capacity() == new_min_capacity Allocates memory specified by the new_min_capacity parameter.
+
Note:
It is considered as a bug if the precondition is not met (i.e. if new_min_capacity > (*this).capacity()) and an assertion will be invoked in the debug mode.
+
+

+ + + + +
+ + + + + + + + + + + + + +
+template<class T, class Alloc>
void boost::circular_buffer_space_optimized< T, Alloc >::swap circular_buffer_space_optimized< T, Alloc > &  cb  )  [inline]
+
+ + + + + +
+   + + +

+See the circular_buffer source documentation. +

+

+


+ + + + + + + + + diff --git a/doc/srcdoc/files.html b/doc/srcdoc/files.html new file mode 100644 index 0000000..1f7546f --- /dev/null +++ b/doc/srcdoc/files.html @@ -0,0 +1,37 @@ + + + + + File Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

Circular Buffer File List

Here is a list of all documented files with brief descriptions: + + +
adaptor.hpp [code]
base.hpp [code]
+
+ + + + + + + + + diff --git a/doc/srcdoc/functions.html b/doc/srcdoc/functions.html new file mode 100644 index 0000000..1682a0e --- /dev/null +++ b/doc/srcdoc/functions.html @@ -0,0 +1,115 @@ + + + + + Compound Member Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+
All | Functions | Typedefs
+
a | b | c | d | e | f | g | i | m | o | p | r | s | v | ~
+ +

+ +

+Here is a list of all documented class members with links to the class documentation for each member:

- a -

+

- b -

+

- c -

+

- d -

+

- e -

+

- f -

+

- g -

+

- i -

+

- m -

+

- o -

+

- p -

+

- r -

+

- s -

+

- v -

+

- ~ -

+
+ + + + + + + + + diff --git a/doc/srcdoc/functions_func.html b/doc/srcdoc/functions_func.html new file mode 100644 index 0000000..ebcf139 --- /dev/null +++ b/doc/srcdoc/functions_func.html @@ -0,0 +1,101 @@ + + + + + Compound Member Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+
All | Functions | Typedefs
+
a | b | c | d | e | f | g | i | m | o | p | r | s | ~
+ +

+ +

+

- a -

+

- b -

+

- c -

+

- d -

+

- e -

+

- f -

+

- g -

+

- i -

+

- m -

+

- o -

+

- p -

+

- r -

+

- s -

+

- ~ -

+
+ + + + + + + + + diff --git a/doc/srcdoc/functions_type.html b/doc/srcdoc/functions_type.html new file mode 100644 index 0000000..d9e2f57 --- /dev/null +++ b/doc/srcdoc/functions_type.html @@ -0,0 +1,50 @@ + + + + + Compound Member Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+
All | Functions | Typedefs
+ +

+

+
+ + + + + + + + + diff --git a/doc/srcdoc/hierarchy.html b/doc/srcdoc/hierarchy.html new file mode 100644 index 0000000..675c82c --- /dev/null +++ b/doc/srcdoc/hierarchy.html @@ -0,0 +1,39 @@ + + + + + Hierarchical Index + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

Circular Buffer Class Hierarchy

This inheritance list is sorted roughly, but not completely, alphabetically: +
+ + + + + + + + + diff --git a/doc/srcdoc/index.html b/doc/srcdoc/index.html new file mode 100644 index 0000000..0f02b8a --- /dev/null +++ b/doc/srcdoc/index.html @@ -0,0 +1,35 @@ + + + + + Main Page + + + + + + + + + + + + +
HomeLibrariesPeopleFAQMore
+
+ +
Main Page | Class Hierarchy | Class List | File List | Class Members
+

Circular Buffer Documentation

+

+

3.6


+ + + + + + + + + diff --git a/doc/srcdoc/stylesheet.css b/doc/srcdoc/stylesheet.css new file mode 100644 index 0000000..7f4f168 --- /dev/null +++ b/doc/srcdoc/stylesheet.css @@ -0,0 +1,48 @@ +H1 { text-align: center; } +CAPTION { font-weight: bold } +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal } +A.codeRef { font-weight: normal } +A:hover { text-decoration: underline } +DL.el { margin-left: -1cm } +DIV.fragment { width: 100%; border: none } +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #f4f4ff; font-weight: bold; } +TD.mdname1 { background-color: #f4f4ff; font-weight: bold; color: #602020; } +TD.mdname { background-color: #f4f4ff; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } +DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } +BODY { background: white; color: black } +EM.mdesc { font-size: smaller } +TD.indexkey { + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TD.indexvalue { + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +span.keyword { color: blue } +span.keywordtype { color: black } +span.keywordflow { color: black } +span.comment { color: green } +span.preprocessor { color: red } +span.stringliteral { color: black } +span.charliteral { color: black } diff --git a/doc/stylesheet.css b/doc/stylesheet.css new file mode 100644 index 0000000..7f4f168 --- /dev/null +++ b/doc/stylesheet.css @@ -0,0 +1,48 @@ +H1 { text-align: center; } +CAPTION { font-weight: bold } +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal } +A.codeRef { font-weight: normal } +A:hover { text-decoration: underline } +DL.el { margin-left: -1cm } +DIV.fragment { width: 100%; border: none } +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #f4f4ff; font-weight: bold; } +TD.mdname1 { background-color: #f4f4ff; font-weight: bold; color: #602020; } +TD.mdname { background-color: #f4f4ff; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } +DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } +BODY { background: white; color: black } +EM.mdesc { font-size: smaller } +TD.indexkey { + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +TD.indexvalue { + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px +} +span.keyword { color: blue } +span.keywordtype { color: black } +span.keywordflow { color: black } +span.comment { color: green } +span.preprocessor { color: red } +span.stringliteral { color: black } +span.charliteral { color: black } diff --git a/include/boost/circular_buffer.hpp b/include/boost/circular_buffer.hpp new file mode 100644 index 0000000..ab01b71 --- /dev/null +++ b/include/boost/circular_buffer.hpp @@ -0,0 +1,62 @@ +// Circular buffer library header file. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_HPP) +#define BOOST_CIRCULAR_BUFFER_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include + +// Debug support control. +#if defined(NDEBUG) || defined(BOOST_DISABLE_CB_DEBUG) + #define BOOST_CB_ASSERT(Expr) ((void)0) + #define BOOST_CB_ENABLE_DEBUG 0 +#else + #include + #define BOOST_CB_ASSERT(Expr) BOOST_ASSERT(Expr) + #define BOOST_CB_ENABLE_DEBUG 1 +#endif + +// The macro definition which checks if Iterator::value_type is convertible to Type. +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0550) || \ + BOOST_WORKAROUND(__MWERKS__, <= 0x2407) || \ + BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) ((void)0) +#else + #include + #include + #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) \ + BOOST_STATIC_ASSERT((is_convertible::value_type, Type>::value)); +#endif + +// Exception handling macros. +#if !defined(BOOST_NO_EXCEPTIONS) + #define BOOST_CB_TRY try { + #define BOOST_CB_UNWIND(action) } catch(...) { action; throw; } +#else + #define BOOST_CB_TRY { + #define BOOST_CB_UNWIND(action) } +#endif + +#include "circular_buffer_fwd.hpp" +#include "circular_buffer/debug.hpp" +#include "circular_buffer/details.hpp" +#include "circular_buffer/base.hpp" +#include "circular_buffer/adaptor.hpp" + +#undef BOOST_CB_UNWIND +#undef BOOST_CB_TRY +#undef BOOST_CB_IS_CONVERTIBLE +#undef BOOST_CB_ENABLE_DEBUG +#undef BOOST_CB_ASSERT + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_HPP) diff --git a/include/boost/circular_buffer/adaptor.hpp b/include/boost/circular_buffer/adaptor.hpp new file mode 100644 index 0000000..93ae54b --- /dev/null +++ b/include/boost/circular_buffer/adaptor.hpp @@ -0,0 +1,585 @@ +// Implementation of the circular buffer adaptor. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP) +#define BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +namespace boost { + +/*! + \class circular_buffer_space_optimized + \brief Space optimized circular buffer container adaptor. + \param T The type of the elements stored in the space optimized circular buffer. + \param Alloc The allocator type used for all internal memory management. + \author Jan Gaspar + \version 1.3 + \date 2004 + + For more information how to use the space optimized circular + buffer see the + documentation. +*/ +template +class circular_buffer_space_optimized : private circular_buffer { +public: +// Typedefs + + typedef typename circular_buffer::value_type value_type; + typedef typename circular_buffer::pointer pointer; + typedef typename circular_buffer::const_pointer const_pointer; + typedef typename circular_buffer::reference reference; + typedef typename circular_buffer::const_reference const_reference; + typedef typename circular_buffer::size_type size_type; + typedef typename circular_buffer::difference_type difference_type; + typedef typename circular_buffer::allocator_type allocator_type; + typedef typename circular_buffer::param_value_type param_value_type; + typedef typename circular_buffer::const_iterator const_iterator; + typedef typename circular_buffer::iterator iterator; + typedef typename circular_buffer::const_reverse_iterator const_reverse_iterator; + typedef typename circular_buffer::reverse_iterator reverse_iterator; + +// Inherited + + using circular_buffer::get_allocator; + using circular_buffer::begin; + using circular_buffer::end; + using circular_buffer::rbegin; + using circular_buffer::rend; + using circular_buffer::at; + using circular_buffer::front; + using circular_buffer::back; + using circular_buffer::data; + using circular_buffer::size; + using circular_buffer::max_size; + using circular_buffer::empty; + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + reference operator [] (size_type n) { return circular_buffer::operator[](n); } + return_value_type operator [] (size_type n) const { return circular_buffer::operator[](n); } +#else + using circular_buffer::operator[]; +#endif + +private: +// Member variables + + //! The capacity of the optimized circular buffer. + size_type m_capacity; + + //! The lowest guaranteed capacity of the adapted circular buffer. + size_type m_min_capacity; + +public: +// Overridden + + //! See the circular_buffer source documentation. + bool full() const { return size() == capacity(); } + + //! Return the minimal guaranteed amount of allocated memory. + /*! + The allocated memory will never drop under this value. + */ + size_type min_capacity() const { return m_min_capacity; } + + //! Change the minimal guaranteed amount of allocated memory. + /*! + \pre (*this).capacity() >= new_min_capacity + \post (*this).min_capacity() == new_min_capacity + Allocates memory specified by the new_min_capacity parameter. + \note It is considered as a bug if the precondition is not met (i.e. if + new_min_capacity > (*this).capacity()) and an assertion + will be invoked in the debug mode. + */ + void set_min_capacity(size_type new_min_capacity) { + BOOST_CB_ASSERT(capacity() >= new_min_capacity); // check for too large new min_capacity + m_min_capacity = new_min_capacity; + if (new_min_capacity > circular_buffer::capacity()) + circular_buffer::set_capacity(new_min_capacity); + else + check_high_capacity(); + } + + //! See the circular_buffer source documentation. + size_type capacity() const { return m_capacity; } + +#if defined(BOOST_CB_TEST) + + //! Return the current capacity of the adapted circular buffer. + /*! + \note This method is not intended to be used directly by the user. + It is defined only for testing purposes. + */ + size_type internal_capacity() const { return circular_buffer::capacity(); } + +#endif // #if defined(BOOST_CB_TEST) + + //! See the circular_buffer source documentation. + /*! + \pre (*this).min_capacity() <= new_capacity + \note It is considered as a bug if the precondition is not met (i.e. if + new_capacity > (*this).min_capacity()) and an assertion + will be invoked in the debug mode. + */ + void set_capacity(size_type new_capacity, bool remove_front = true) { + BOOST_CB_ASSERT(new_capacity >= min_capacity()); // check for too low new capacity + if (new_capacity < circular_buffer::capacity()) + circular_buffer::set_capacity(new_capacity, remove_front); + m_capacity = new_capacity; + } + + //! See the circular_buffer source documentation. + void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) { + if (new_size > size()) { + if (new_size > capacity()) + m_capacity = new_size; + insert(end(), new_size - size(), item); + } else { + if (remove_front) + erase(begin(), end() - new_size); + else + erase(begin() + new_size, end()); + } + } + + //! Create an empty space optimized circular buffer with a given capacity. + /*! + \param capacity The capacity of the buffer. + \param min_capacity The minimal guaranteed amount of allocated memory. + (The metrics of the min_capacity is number of items.) + \param alloc The allocator. + \pre capacity >= min_capacity + \post (*this).capacity() == capacity \&\& (*this).size == 0
+ Allocates memory specified by the min_capacity parameter. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \note It is considered as a bug if the precondition is not met (i.e. if + capacity < min_capacity) and an assertion will be invoked + in the debug mode. + */ + explicit circular_buffer_space_optimized( + size_type capacity, + size_type min_capacity = 0, + const allocator_type& alloc = allocator_type()) + : circular_buffer(min_capacity, alloc) + , m_capacity(capacity) + , m_min_capacity(min_capacity) { + BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity + } + + //! Create a full space optimized circular buffer filled with copies of item. + /*! + \param capacity The capacity of the buffer. + \param min_capacity The minimal guaranteed amount of allocated memory. + (The metrics of the min_capacity is number of items.) + \param item The item to be filled with. + \param alloc The allocator. + \pre capacity >= min_capacity + \post (*this).size() == capacity \&\& (*this)[0] == (*this)[1] == ... == (*this).back() == item + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note It is considered as a bug if the precondition is not met (i.e. if + capacity < min_capacity) and an assertion will be invoked + in the debug mode. + */ + circular_buffer_space_optimized( + size_type capacity, + size_type min_capacity, + param_value_type item, + const allocator_type& alloc = allocator_type()) + : circular_buffer(capacity, item, alloc) + , m_capacity(capacity) + , m_min_capacity(min_capacity) { + BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity + } + + // Default copy constructor + + //! Create a space optimized circular buffer with a copy of a range. + /*! + \param capacity The capacity of the buffer. + \param min_capacity The minimal guaranteed amount of allocated memory. + (The metrics of the min_capacity is number of items.) + \param first The beginning of the range. + \param last The end of the range. + \param alloc The allocator. + \pre capacity >= min_capacity and valid range [first, last). + \post (*this).capacity() == capacity
+ Allocates at least as much memory as specified by the + min_capacity parameter.
+ If the number of items to copy from the range + [first, last) is greater than the specified + capacity then only elements from the range + [last - capacity, last) will be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note It is considered as a bug if the precondition is not met (i.e. if + capacity < min_capacity) and an assertion will be invoked + in the debug mode. + */ + template + circular_buffer_space_optimized( + size_type capacity, + size_type min_capacity, + InputIterator first, + InputIterator last, + const allocator_type& alloc = allocator_type()) + : circular_buffer( + init_capacity(capacity, min_capacity, first, last), first, last, alloc) + , m_capacity(capacity) + , m_min_capacity(min_capacity) { + BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + } + + // Default destructor + + // Default assign operator + + //! See the circular_buffer source documentation. + void assign(size_type n, param_value_type item) { + if (n > m_capacity) + m_capacity = n; + circular_buffer::assign(n, item); + } + + //! See the circular_buffer source documentation. + template + void assign(InputIterator first, InputIterator last) { + circular_buffer::assign(first, last); + size_type capacity = circular_buffer::capacity(); + if (capacity > m_capacity) + m_capacity = capacity; + } + + //! See the circular_buffer source documentation. + void swap(circular_buffer_space_optimized& cb) { + std::swap(m_capacity, cb.m_capacity); + std::swap(m_min_capacity, cb.m_min_capacity); + circular_buffer::swap(cb); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void push_back(param_value_type item) { + check_low_capacity(); + circular_buffer::push_back(item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void push_back() { push_back(value_type()); } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void push_front(param_value_type item) { + check_low_capacity(); + circular_buffer::push_front(item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void push_front() { push_front(value_type()); } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void pop_back() { + circular_buffer::pop_back(); + check_high_capacity(); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void pop_front() { + circular_buffer::pop_front(); + check_high_capacity(); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator insert(iterator pos, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(); + return circular_buffer::insert(begin() + index, item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator insert(iterator pos) { return insert(pos, value_type()); } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void insert(iterator pos, size_type n, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(n); + circular_buffer::insert(begin() + index, n, item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + template + void insert(iterator pos, InputIterator first, InputIterator last) { + insert(pos, first, last, cb_details::cb_iterator_category_traits::tag()); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator rinsert(iterator pos, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(); + return circular_buffer::rinsert(begin() + index, item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator rinsert(iterator pos) { return rinsert(pos, value_type()); } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + void rinsert(iterator pos, size_type n, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(n); + circular_buffer::rinsert(begin() + index, n, item); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + template + void rinsert(iterator pos, InputIterator first, InputIterator last) { + rinsert(pos, first, last, cb_details::cb_iterator_category_traits::tag()); + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator erase(iterator pos) { + iterator it = circular_buffer::erase(pos); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! See the circular_buffer source documentation. + /*! + \warning The rules for iterator invalidation differ from the original + circular_buffer. See the + documentation. + */ + iterator erase(iterator first, iterator last) { + iterator it = circular_buffer::erase(first, last); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! See the circular_buffer source documentation. + void clear() { erase(begin(), end()); } + +private: +// Helper methods + + //! Ensure the reserve for possible growth up. + size_type ensure_reserve(size_type new_capacity, size_type size) const { + if (size + new_capacity / 5 >= new_capacity) + new_capacity *= 2; // ensure at least 20% reserve + if (new_capacity > capacity()) + return capacity(); + return new_capacity; + } + + //! Check for low capacity. + /* + \post If the capacity is low it will be increased. + */ + void check_low_capacity(size_type n = 1) { + size_type new_size = size() + n; + size_type new_capacity = circular_buffer::capacity(); + if (new_size > new_capacity) { + if (new_capacity == 0) + new_capacity = 1; + for (; new_size > new_capacity; new_capacity *= 2); + circular_buffer::set_capacity( + ensure_reserve(new_capacity, new_size)); + } + } + + //! Check for high capacity. + /* + \post If the capacity is high it will be decreased. + */ + void check_high_capacity() { + size_type new_capacity = circular_buffer::capacity(); + while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations + new_capacity /= 2; + if (new_capacity <= min_capacity()) { + new_capacity = min_capacity(); + break; + } + } + circular_buffer::set_capacity( + ensure_reserve(new_capacity, size())); + } + + //! Determine the initial capacity. + template + static size_type init_capacity(size_type capacity, size_type min_capacity, InputIterator first, InputIterator last) { + BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); + return std::min(capacity, std::max(min_capacity, + static_cast(std::distance(first, last)))); + } + + //! Helper insert method. + template + void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) { + insert(pos, (size_type)n, item); + } + + //! Helper insert method. + template + void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) { + size_type index = pos - begin(); + check_low_capacity(std::distance(first, last)); + circular_buffer::insert(begin() + index, first, last); + } + + //! Helper rinsert method. + template + void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) { + rinsert(pos, (size_type)n, item); + } + + //! Helper rinsert method. + template + void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) { + size_type index = pos - begin(); + check_low_capacity(std::distance(first, last)); + circular_buffer::rinsert(begin() + index, first, last); + } +}; + +// Non-member functions + +//! Test two space optimized circular buffers for equality. +template +inline bool operator == (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return lhs.size() == rhs.size() && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +//! Lexicographical comparison. +template +inline bool operator < (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return std::lexicographical_compare( + lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + +//! Test two space optimized circular buffers for non-equality. +template +inline bool operator != (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(lhs == rhs); +} + +//! Lexicographical comparison. +template +inline bool operator > (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return rhs < lhs; +} + +//! Lexicographical comparison. +template +inline bool operator <= (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(rhs < lhs); +} + +//! Lexicographical comparison. +template +inline bool operator >= (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(lhs < rhs); +} + +//! Swap the contents of two space optimized circular buffers. +template +inline void swap(circular_buffer_space_optimized& lhs, + circular_buffer_space_optimized& rhs) { + lhs.swap(rhs); +} + +#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_ADAPTOR_HPP) diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp new file mode 100644 index 0000000..65b4ee2 --- /dev/null +++ b/include/boost/circular_buffer/base.hpp @@ -0,0 +1,1439 @@ +// Implementation of the base circular buffer. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP) +#define BOOST_CIRCULAR_BUFFER_BASE_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_EXCEPTIONS) + #include +#endif +#if BOOST_CB_ENABLE_DEBUG + #include +#endif + +namespace boost { + +/*! + \class circular_buffer + \brief Circular buffer - a STL compliant container. + \param T The type of the elements stored in the circular buffer. + \param Alloc The allocator type used for all internal memory management. + \author Jan Gaspar + \version 3.6 + \date 2004 + + For more information how to use the circular buffer see the + documentation. +*/ +template +class circular_buffer : cb_details::cb_iterator_registry { + +// Requirements + BOOST_CLASS_REQUIRE(T, boost, CopyConstructibleConcept); + +public: +// Basic types + + //! The type of the elements stored in the circular buffer. + typedef typename Alloc::value_type value_type; + + //! Pointer to the element. + typedef typename Alloc::pointer pointer; + + //! Const pointer to the element. + typedef typename Alloc::const_pointer const_pointer; + + //! Reference to the element. + typedef typename Alloc::reference reference; + + //! Const reference to the element. + typedef typename Alloc::const_reference const_reference; + + //! Distance type. + /*! + A signed integral type used to represent the distance between two iterators. + */ + typedef typename Alloc::difference_type difference_type; + + //! Size type. + /*! + An unsigned integral type that can represent any nonnegative value of the container's distance type. + */ + typedef typename Alloc::size_type size_type; + + //! The type of the allocator used in the circular buffer. + typedef Alloc allocator_type; + + //! Return the allocator. + allocator_type get_allocator() const { return m_alloc; } + + //! Return the allocator. + /*! + \note This method was added in order to optimize obtaining of the allocator with a state, + although use of stateful allocators in STL is discouraged. + */ + allocator_type& get_allocator() { return m_alloc; } + +// Helper types + + // Define a type that represents the "best" way to pass the value_type to a method. + typedef typename call_traits::param_type param_value_type; + + // Define a type that represents the "best" way to return the value_type from a const method. + typedef typename call_traits::param_type return_value_type; + +// Iterators + + //! Const (random access) iterator used to iterate through a circular buffer. + typedef cb_details::cb_iterator< circular_buffer, cb_details::cb_const_traits > const_iterator; + + //! Iterator (random access) used to iterate through a circular buffer. + typedef cb_details::cb_iterator< circular_buffer, cb_details::cb_nonconst_traits > iterator; + + //! Const iterator used to iterate backwards through a circular buffer. + typedef reverse_iterator const_reverse_iterator; + + //! Iterator used to iterate backwards through a circular buffer. + typedef reverse_iterator reverse_iterator; + +private: +// Member variables + + //! The internal buffer used for storing elements in the circular buffer. + pointer m_buff; + + //! The internal buffer's end (end of the storage space). + pointer m_end; + + //! The virtual beginning of the circular buffer (the leftmost element). + pointer m_first; + + //! The virtual end of the circular buffer (one behind the rightmost element). + pointer m_last; + + //! The number of items currently stored in the circular buffer. + size_type m_size; + + //! The allocator. + allocator_type m_alloc; + +// Friends +#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + friend iterator; + friend const_iterator; +#else + friend struct iterator; + friend struct const_iterator; +#endif + +public: +// Element access + + //! Return an iterator pointing to the beginning of the circular buffer. + iterator begin() { return iterator(this, empty() ? 0 : m_first); } + + //! Return an iterator pointing to the end of the circular buffer. + iterator end() { return iterator(this, 0); } + + //! Return a const iterator pointing to the beginning of the circular buffer. + const_iterator begin() const { return const_iterator(this, empty() ? 0 : m_first); } + + //! Return a const iterator pointing to the end of the circular buffer. + const_iterator end() const { return const_iterator(this, 0); } + + //! Return a reverse iterator pointing to the beginning of the reversed circular buffer. + reverse_iterator rbegin() { return reverse_iterator(end()); } + + //! Return a reverse iterator pointing to the end of the reversed circular buffer. + reverse_iterator rend() { return reverse_iterator(begin()); } + + //! Return a const reverse iterator pointing to the beginning of the reversed circular buffer. + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + + //! Return a const reverse iterator pointing to the end of the reversed circular buffer. + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + //! Return the element at the index position. + /*! + \pre *(this).size() > index + */ + reference operator [] (size_type index) { + BOOST_CB_ASSERT(index < size()); // check for invalid index + return *add(m_first, index); + } + + //! Return the element at the index position. + /*! + \pre *(this).size() > index + */ + return_value_type operator [] (size_type index) const { + BOOST_CB_ASSERT(index < size()); // check for invalid index + return *add(m_first, index); + } + + //! Return the element at the index position. + /*! + \throws std::out_of_range thrown when the index is invalid. + */ + reference at(size_type index) { + check_position(index); + return (*this)[index]; + } + + //! Return the element at the index position. + /*! + \throws std::out_of_range thrown when the index is invalid. + */ + return_value_type at(size_type index) const { + check_position(index); + return (*this)[index]; + } + + //! Return the first (leftmost) element. + /*! + \pre !*(this).empty() + */ + reference front() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + return *m_first; + } + + //! Return the last (rightmost) element. + /*! + \pre !*(this).empty() + */ + reference back() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + return *((m_last == m_buff ? m_end : m_last) - 1); + } + + //! Return the first (leftmost) element. + /*! + \pre !*(this).empty() + */ + return_value_type front() const { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + return *m_first; + } + + //! Return the last (rightmost) element. + /*! + \pre !*(this).empty() + */ + return_value_type back() const { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + return *((m_last == m_buff ? m_end : m_last) - 1); + } + + //! Return pointer to data stored in the circular buffer as a continuous array of values. + /*! + This method can be useful e.g. when passing the stored data into the legacy C API. + \post \&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this).back() + \return 0 if empty. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + pointer data() { + if (empty()) + return 0; + if (m_first < m_last || m_last == m_buff) + return m_first; + size_type constructed = 0; + pointer src = m_first; + pointer dest = m_buff; + pointer tmp = 0; + BOOST_CB_TRY + tmp = allocate(1); + for (pointer first = m_first; dest < src; src = first) { + for (size_type ii = 0; src < m_end; ++src, ++dest, ++ii) { + if (dest == first) { + first += ii; + break; + } + if (is_uninitialized(dest)) { + m_alloc.construct(dest, *src); + ++constructed; + } else { + m_alloc.construct(tmp, *src); + BOOST_CB_TRY + replace(src, *dest); + BOOST_CB_UNWIND( + destroy_item(tmp); + tidy(src); + ) + BOOST_CB_TRY + replace(dest, *tmp); + BOOST_CB_UNWIND( + destroy_item(tmp); + tidy(dest); + ) + destroy_item(tmp); + } + } + } + deallocate(tmp, 1); + BOOST_CB_UNWIND( + deallocate(tmp, 1); + m_last += constructed; + m_size += constructed; + ) + for (dest = m_buff + size(); dest < m_end; ++dest) + destroy_item(dest); + m_first = m_buff; + m_last = add(m_buff, size()); + return m_buff; + } + +// Size and capacity + + //! Return the number of elements currently stored in the circular buffer. + size_type size() const { return m_size; } + + //! Return the largest possible size (or capacity) of the circular buffer. + size_type max_size() const { return m_alloc.max_size(); } + + //! Is the circular buffer empty? + /*! + \return true if there are no elements stored in the circular buffer. + \return false otherwise. + */ + bool empty() const { return size() == 0; } + + //! Is the circular buffer full? + /*! + \return true if the number of elements stored in the circular buffer + equals the capacity of the circular buffer. + \return false otherwise. + */ + bool full() const { return size() == capacity(); } + + //! Return the capacity of the circular buffer. + size_type capacity() const { return m_end - m_buff; } + + //! Change the capacity of the circular buffer. + /*! + \param new_capacity The new capacity. + \param remove_front This parameter plays its role only if the + current number of elements stored in the circular buffer + is greater than the desired new capacity. If set to + true then the first (leftmost) elements + will be removed. If set to false then the + last (leftmost) elements will be removed. + \post (*this).capacity() == new_capacity
+ If the current number of elements stored in the circular + buffer is greater than the desired new capacity then + ((*this).size() - new_capacity) elements + will be removed according to the remove_front + parameter. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void set_capacity(size_type new_capacity, bool remove_front = true) { + if (new_capacity == capacity()) + return; + pointer buff = allocate(new_capacity); + size_type new_size = std::min(new_capacity, size()); + BOOST_CB_TRY + if (remove_front) + cb_details::uninitialized_copy(end() - new_size, end(), buff, m_alloc); + else + cb_details::uninitialized_copy(begin(), begin() + new_size, buff, m_alloc); + BOOST_CB_UNWIND(deallocate(buff, new_capacity)) + destroy(); + m_size = new_size; + m_buff = m_first = buff; + m_end = m_buff + new_capacity; + m_last = add(m_buff, size()); + } + + //! Change the size of the circular buffer. + /*! + \param new_size The new size. + \param item See the postcondition. + \param remove_front This parameter plays its role only if the + current number of elements stored in the circular buffer + is greater than the desired new capacity. If set to + true then the first (leftmost) elements + will be removed. If set to false then the + last (leftmost) elements will be removed. + \post (*this).size() == new_size
+ If the new size is greater than the current size, the rest + of the circular buffer is filled with copies of item. + In case the resulting size exceeds the current capacity + the capacity is set to new_size. + If the new size is lower than the current size then + ((*this).size() - new_size) elements will be removed + according to the remove_front parameter. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void resize(size_type new_size, param_value_type item = T(), bool remove_front = true) { + if (new_size > size()) { + if (new_size > capacity()) + set_capacity(new_size); + insert(end(), new_size - size(), item); + } else { + if (remove_front) + erase(begin(), end() - new_size); + else + erase(begin() + new_size, end()); + } + } + +// Construction/Destruction + + //! Create an empty circular buffer with a given capacity. + /*! + \post (*this).capacity() == capacity \&\& (*this).size == 0 + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + */ + explicit circular_buffer( + size_type capacity, + const allocator_type& alloc = allocator_type()) + : m_size(0), m_alloc(alloc) { + m_first = m_last = m_buff = allocate(capacity); + m_end = m_buff + capacity; + } + + //! Create a full circular buffer with a given capacity and filled with copies of item. + /*! + \post (*this).size() == capacity \&\& (*this)[0] == (*this)[1] == ... == (*this).back() == item + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + */ + circular_buffer( + size_type capacity, + param_value_type item, + const allocator_type& alloc = allocator_type()) + : m_size(capacity), m_alloc(alloc) { + m_first = m_last = m_buff = allocate(capacity); + m_end = m_buff + capacity; + BOOST_CB_TRY + cb_details::uninitialized_fill_n(m_buff, size(), item, m_alloc); + BOOST_CB_UNWIND(deallocate(m_buff, capacity)) + } + + //! Copy constructor. + /*! + \post *this == cb + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + */ + circular_buffer(const circular_buffer& cb) + : m_size(cb.size()), m_alloc(cb.get_allocator()) { + m_first = m_last = m_buff = allocate(cb.capacity()); + BOOST_CB_TRY + m_end = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc); + BOOST_CB_UNWIND(deallocate(m_buff, cb.capacity())) + } + + //! Create a circular buffer with a copy of a range. + /*! + \pre Valid range [first, last). + \post (*this).capacity() == capacity
+ If the number of items to copy from the range + [first, last) is greater than the specified + capacity then only elements from the range + [last - capacity, last) will be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + */ + template + circular_buffer( + size_type capacity, + InputIterator first, + InputIterator last, + const allocator_type& alloc = allocator_type()) + : m_alloc(alloc) { + BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + m_first = m_buff = allocate(capacity); + m_end = m_buff + capacity; + size_type diff = std::distance(first, last); + if (diff > capacity) { + std::advance(first, diff - capacity); + m_size = capacity; + m_last = m_buff; + } else { + m_size = diff; + if (diff == capacity) + m_last = m_buff; + else + m_last = m_buff + size(); + } + BOOST_CB_TRY + cb_details::uninitialized_copy(first, last, m_buff, m_alloc); + BOOST_CB_UNWIND(deallocate(m_buff, capacity)) + } + + //! Destructor. + ~circular_buffer() { destroy(); } + +private: +// Helper functors + + // Functor for assigning n items. + struct assign_n { + size_type m_n; + param_value_type m_item; + allocator_type& m_alloc; + explicit assign_n(size_type n, param_value_type item, allocator_type& alloc) : m_n(n), m_item(item), m_alloc(alloc) {} + void operator () (pointer p) const { + cb_details::uninitialized_fill_n(p, m_n, m_item, m_alloc); + } + private: + assign_n& operator = (const assign_n&); // do not generate + }; + + // Functor for assigning range of items. + template + struct assign_range { + InputIterator m_first; + InputIterator m_last; + allocator_type& m_alloc; + explicit assign_range(InputIterator first, InputIterator last, allocator_type& alloc) : m_first(first), m_last(last), m_alloc(alloc) {} + void operator () (pointer p) const { + cb_details::uninitialized_copy(m_first, m_last, p, m_alloc); + } + private: + assign_range& operator = (const assign_range&); // do not generate + }; + +public: +// Assign methods + + //! Assignment operator. + /*! + \post *this == cb + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + circular_buffer& operator = (const circular_buffer& cb) { + if (this == &cb) + return *this; + pointer buff = allocate(cb.capacity()); + BOOST_CB_TRY + pointer last = cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc); + destroy(); + m_size = cb.size(); + m_first = m_buff = buff; + m_end = m_buff + cb.capacity(); + m_last = full() ? m_buff : last; + BOOST_CB_UNWIND(deallocate(buff, cb.capacity())) + return *this; + } + + //! Assign n items into the circular buffer. + /*! + \post (*this).size() == n \&\& + (*this)[0] == (*this)[1] == ... == (*this).back() == item
+ If the number of items to be assigned exceeds + the capacity of the circular buffer the capacity + is increased to n otherwise it stays unchanged. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void assign(size_type n, param_value_type item) { do_assign(n, assign_n(n, item, m_alloc)); } + + //! Assign a copy of range. + /*! + \pre Valid range [first, last). + \post (*this).size() == std::distance(first, last)
+ If the number of items to be assigned exceeds + the capacity of the circular buffer the capacity + is set to that number otherwise is stays unchanged. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if standard allocator is used). + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + template + void assign(InputIterator first, InputIterator last) { + assign(first, last, cb_details::cb_iterator_category_traits::tag()); + } + + //! Swap the contents of two circular buffers. + /*! + \post this contains elements of cb and vice versa. + \note For iterator invalidation see the documentation. + */ + void swap(circular_buffer& cb) { + std::swap(m_alloc, cb.m_alloc); // in general this is not necessary, + // because allocators should not have state + std::swap(m_buff, cb.m_buff); + std::swap(m_end, cb.m_end); + std::swap(m_first, cb.m_first); + std::swap(m_last, cb.m_last); + std::swap(m_size, cb.m_size); +#if BOOST_CB_ENABLE_DEBUG + invalidate_all_iterators(); + cb.invalidate_all_iterators(); +#endif + } + +// push and pop + + //! Insert a new element at the end. + /*! + \post (*this).back() == item
+ If the circular buffer is full, the first (leftmost) element will be removed. + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void push_back(param_value_type item) { + if (full()) { + if (empty()) + return; + replace_last(item); + increment(m_last); + m_first = m_last; + } else { + m_alloc.construct(m_last, item); + increment(m_last); + ++m_size; + } + } + + //! Insert a new element with the default value at the end. + /*! + \post (*this).back() == value_type()
+ If the circular buffer is full, the first (leftmost) element will be removed. + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void push_back() { push_back(value_type()); } + + //! Insert a new element at the start. + /*! + \post (*this).front() == item
+ If the circular buffer is full, the last (rightmost) element will be removed. + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void push_front(param_value_type item) { + if (full()) { + if (empty()) + return; + replace_first(item); + m_last = m_first; + } else { + decrement(m_first); + BOOST_CB_TRY + m_alloc.construct(m_first, item); + BOOST_CB_UNWIND(increment(m_first)) + ++m_size; + } + } + + //! Insert a new element with the default value at the start. + /*! + \post (*this).front() == value_type()
+ If the circular buffer is full, the last (rightmost) element will be removed. + \throws Whatever T::T(const T&) throws. + \note For iterator invalidation see the documentation. + */ + void push_front() { push_front(value_type()); } + + //! Remove the last (rightmost) element. + /*! + \pre !*(this).empty() + \pre iterator it = ((*this).end() - 1) + \post ((*this).end() - 1) != it + \note For iterator invalidation see the documentation. + */ + void pop_back() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + decrement(m_last); + destroy_item(m_last); + --m_size; + } + + //! Remove the first (leftmost) element. + /*! + \pre !*(this).empty() + \pre iterator it = (*this).begin() + \post (*this).begin() != it + \note For iterator invalidation see the documentation. + */ + void pop_front() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + destroy_item(m_first); + increment(m_first); + --m_size; + } + +private: +// Helper wrappers + + // Iterator dereference wrapper. + template + struct iterator_wrapper { + mutable InputIterator m_it; + explicit iterator_wrapper(InputIterator it) : m_it(it) {} + InputIterator get_reference() const { return m_it++; } + }; + + // Item dereference wrapper. + struct item_wrapper { + const_pointer m_item; + explicit item_wrapper(param_value_type item) : m_item(&item) {} + const_pointer get_reference() const { return m_item; } + }; + +public: +// Insert + + //! Insert the item before the given position. + /*! + \pre Valid pos iterator. + \post The item will be inserted at the position pos.
+ If the circular buffer is full, the first (leftmost) element will be removed. + \return iterator to the inserted element. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + iterator insert(iterator pos, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + if (full() && pos == begin()) + return begin(); + if (pos.m_it == 0) { + if (full()) + replace_last(item); + else + m_alloc.construct(m_last, item); + pos.m_it = m_last; + } else { + pointer src = m_last; + pointer dest = m_last; + BOOST_CB_TRY + while (src != pos.m_it) { + decrement(src); + if (dest == m_last && !full()) + m_alloc.construct(dest, *src); + else + replace(dest, *src); + decrement(dest); + } + replace(pos.m_it, item); + BOOST_CB_UNWIND( + if (dest == m_last) { + if (full()) { + increment(m_first); + --m_size; + } + } else { + if (!full()) { + increment(m_last); + ++m_size; + } + tidy(dest); + } + ) + } + increment(m_last); + if (full()) + m_first = m_last; + else + ++m_size; + return iterator(this, pos.m_it); + } + + //! Insert a new element with the default value before the given position. + /*! + \post value_type() will be inserted at the position pos.
+ If the circular buffer is full, the first (leftmost) element will be removed. + \return iterator to the inserted element. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + iterator insert(iterator pos) { return insert(pos, value_type()); } + + //! Insert n copies of the item before the given position. + /*! + \pre Valid pos iterator. + \post This operation preserves the capacity of the circular buffer. + If the insertion would result in exceeding the capacity + of the circular buffer then the necessary number of elements + from the beginning (left) of the circular buffer will be removed + or not all n elements will be inserted or both.
+ Example:
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, (size_t)5, 6);
+ (If the operation won't preserve capacity, the buffer + would look like this |1|2|6|6|6|6|6|3|4|)
+ RESULTING circular buffer |6|6|6|6|3|4| - capacity: 6, size: 6
+ \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + void insert(iterator pos, size_type n, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + if (n == 0) + return; + size_type copy = capacity() - (end() - pos); + if (copy == 0) + return; + if (n > copy) + n = copy; + insert_n_item(pos, n, item_wrapper(item)); + } + + //! Insert the range [first, last) before the given position. + /*! + \pre Valid pos iterator and valid range [first, last). + \post This operation preserves the capacity of the circular buffer. + If the insertion would result in exceeding the capacity + of the circular buffer then the necessary number of elements + from the beginning (left) of the circular buffer will be removed + or not the whole range will be inserted or both. + In case the whole range cannot be inserted it will be inserted just + some elements from the end (right) of the range (see the example).
+ Example:
+ array to insert: int array[] = { 5, 6, 7, 8, 9 };
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, array, array + 5);
+ (If the operation won't preserve capacity, the buffer + would look like this |1|2|5|6|7|8|9|3|4|)
+ RESULTING circular buffer |6|7|8|9|3|4| - capacity: 6, size: 6
+ \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + template + void insert(iterator pos, InputIterator first, InputIterator last) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + insert(pos, first, last, cb_details::cb_iterator_category_traits::tag()); + } + + //! Insert an item before the given position. + /*! + \pre Valid pos iterator. + \post The item will be inserted at the position pos.
+ If the circular buffer is full, the last element (rightmost) will be removed. + \return iterator to the inserted element. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + iterator rinsert(iterator pos, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + if (full() && pos == end()) + return end(); + if (pos == begin()) { + if (full()) { + replace_first(item); + } else { + decrement(m_first); + BOOST_CB_TRY + m_alloc.construct(m_first, item); + BOOST_CB_UNWIND(increment(m_first)) + } + } else { + pointer src = m_first; + pointer dest = m_first; + decrement(dest); + pointer it = map_pointer(pos.m_it); + pointer first = m_first; + decrement(first); + BOOST_CB_TRY + while (src != it) { + if (dest == first && !full()) + m_alloc.construct(dest, *src); + else + replace(dest, *src); + increment(src); + increment(dest); + } + replace((--pos).m_it, item); + BOOST_CB_UNWIND( + if (dest == first) { + if (full()) { + decrement(m_last); + --m_size; + } + } else { + if (!full()) { + m_first = first; + ++m_size; + } + tidy(dest); + } + ) + decrement(m_first); + } + if (full()) + m_last = m_first; + else + ++m_size; + return iterator(this, pos.m_it); + } + + //! Insert a new element with the default value before the given position. + /*! + \post value_type() will be inserted at the position pos.
+ If the circular buffer is full, the last (rightmost) element will be removed. + \return iterator to the inserted element. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + iterator rinsert(iterator pos) { return rinsert(pos, value_type()); } + + //! Insert n copies of the item before the given position. + /*! + \pre Valid pos iterator. + \post This operation preserves the capacity of the circular buffer. + If the insertion would result in exceeding the capacity + of the circular buffer then the necessary number of elements + from the end (right) of the circular buffer will be removed + or not all n elements will be inserted or both.
+ Example:
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, (size_t)5, 6);
+ (If the operation won't preserve capacity, the buffer + would look like this |1|2|6|6|6|6|6|3|4|)
+ RESULTING circular buffer |1|2|6|6|6|6| - capacity: 6, size: 6
+ \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + void rinsert(iterator pos, size_type n, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + rinsert_n_item(pos, n, item_wrapper(item)); + } + + //! Insert the range [first, last) before the given position. + /*! + \pre Valid pos iterator and valid range [first, last). + \post This operation preserves the capacity of the circular buffer. + If the insertion would result in exceeding the capacity + of the circular buffer then the necessary number of elements + from the end (right) of the circular buffer will be removed + or not the whole range will be inserted or both. + In case the whole range cannot be inserted it will be inserted just + some elements from the beginning (left) of the range (see the example).
+ Example:
+ array to insert: int array[] = { 5, 6, 7, 8, 9 };
+ original circular buffer |1|2|3|4| | | - capacity: 6, size: 4
+ position ---------------------^
+ insert(position, array, array + 5);
+ (If the operation won't preserve capacity, the buffer + would look like this |1|2|5|6|7|8|9|3|4|)
+ RESULTING circular buffer |1|2|5|6|7|8| - capacity: 6, size: 6
+ \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \note For iterator invalidation see the documentation. + */ + template + void rinsert(iterator pos, InputIterator first, InputIterator last) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + rinsert(pos, first, last, cb_details::cb_iterator_category_traits::tag()); + } + +// Erase + + //! Erase the element at the given position. + /*! + \pre Valid pos iterator. + \pre size_type old_size = (*this).size() + \post (*this).size() == old_size - 1
+ Removes an element at the position pos. + \return iterator to the first element remaining beyond the removed + element or (*this).end() if no such element exists. + \note For iterator invalidation see the documentation. + */ + iterator erase(iterator pos) { + BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() + pointer next = pos.m_it; + increment(next); + for (pointer p = pos.m_it; next != m_last; p = next, increment(next)) + replace(p, *next); + decrement(m_last); + destroy_item(m_last); + --m_size; +#if BOOST_CB_ENABLE_DEBUG + return empty() ? end() : iterator(this, pos.m_it); +#else + return empty() ? end() : pos; +#endif + } + + //! Erase the range [first, last). + /*! + \pre Valid range [first, last). + \pre size_type old_size = (*this).size() + \post (*this).size() == old_size - std::distance(first, last)
+ Removes the elements from the range [first, last). + \return iterator to the first element remaining beyond the removed + element or (*this).end() if no such element exists. + \note For iterator invalidation see the documentation. + */ + iterator erase(iterator first, iterator last) { + BOOST_CB_ASSERT(first.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(last.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(first.m_buff == last.m_buff); // check for iterators of different containers + BOOST_CB_ASSERT(first <= last); // check for wrong range + if (first == last) + return first; + pointer tmp = first.m_it; + difference_type diff = last - first; + while (last.m_it != 0) + replace((first++).m_it, *last++); + while (first.m_it != 0) + destroy_item((first++).m_it); + m_last = sub(m_last, diff); + m_size -= diff; + return empty() ? end() : iterator(this, tmp); + } + + //! Erase all the stored elements. + /*! + \post (*this).size() == 0 + \note For iterator invalidation see the documentation. + */ + void clear() { + destroy_content(); + m_first = m_last = m_buff; + m_size = 0; + } + +private: +// Debug support + +#if BOOST_CB_ENABLE_DEBUG + + // Predicate determining if the condition for iterator invalidation has been met. + struct is_invalid_condition { + pointer m_p; + explicit is_invalid_condition(pointer p) : m_p(p) {} + bool operator () (const cb_details::cb_iterator_base* p) const { + return ((iterator*)p)->m_it == m_p; + } + }; + +#endif // #if BOOST_CB_ENABLE_DEBUG + +// Helper methods + + //! Check if the index is valid. + void check_position(size_type index) const { + if (index >= size()) + throw_exception(std::out_of_range("circular_buffer")); + } + + //! Increment the pointer. + template + void increment(Pointer0& p) const { + if (++p == m_end) + p = m_buff; + } + + //! Decrement the pointer. + template + void decrement(Pointer0& p) const { + if (p == m_buff) + p = m_end; + --p; + } + + //! Add n to the pointer. + template + Pointer0 add(Pointer0 p, difference_type n) const { + return p + (n < (m_end - p) ? n : n - capacity()); + } + + //! Subtract n from the pointer. + template + Pointer0 sub(Pointer0 p, difference_type n) const { + return p - (n > (p - m_buff) ? n - capacity() : n); + } + + //! Map the null pointer to virtual end of circular buffer. + pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; } + + //! Does the pointer point to the uninitialized memory? + bool is_uninitialized(const_pointer p) const { + return p >= m_last && (m_first < m_last || p < m_first); + } + + //! Create a copy of the item at the given position. + /*! + The copy is created either at uninitialized memory or replaces the old item. + */ + void create_or_replace(pointer pos, param_value_type item) { + if (is_uninitialized(pos)) + m_alloc.construct(pos, item); + else + replace(pos, item); + } + + //! Destroy an item in case it has been created. + /*! + Called when create_or_replace fails. + */ + void destroy_created(pointer pos) { + if (is_uninitialized(pos)) + destroy_item(pos); + } + + //! Replace an element. + void replace(pointer pos, param_value_type item) { + replace(pos, item, cb_details::cb_replace_category_traits::tag()); // invoke optimized operation for given type +#if BOOST_CB_ENABLE_DEBUG + invalidate_iterators(is_invalid_condition(pos)); +#endif + } + + //! Specialized replace method. + void replace(pointer pos, param_value_type item, cb_details::cb_destroy_tag) { + m_alloc.destroy(pos); + m_alloc.construct(pos, item); + } + + //! Specialized replace method. + void replace(pointer pos, param_value_type item, cb_details::cb_assign_tag) { + *pos = item; + } + + //! Replace the first element in the full buffer. + void replace_first(param_value_type item) { + decrement(m_first); + BOOST_CB_TRY + replace(m_first, item); + BOOST_CB_UNWIND( + increment(m_first); + decrement(m_last); + --m_size; + ) + } + + //! Replace the last element in the full buffer. + void replace_last(param_value_type item) { + BOOST_CB_TRY + replace(m_last, item); + BOOST_CB_UNWIND( + decrement(m_last); + --m_size; + ) + } + + //! Tidy up after an exception is thrown. + void tidy(pointer p) { + for (; m_first != p; increment(m_first), --m_size) + destroy_item(m_first); + increment(m_first); + --m_size; + } + + //! Allocate memory. + pointer allocate(size_type n) { + if (n > max_size()) + throw_exception(std::length_error("circular_buffer")); +#if BOOST_CB_ENABLE_DEBUG + pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0); + ::memset(p, cb_details::CB_Unitialized, sizeof(value_type) * n); + return p; +#else + return (n == 0) ? 0 : m_alloc.allocate(n, 0); +#endif + } + + //! Deallocate memory. + void deallocate(pointer p, size_type n) { + if (p != 0) + m_alloc.deallocate(p, n); + } + + //! Destroy an item. + void destroy_item(pointer p) { + m_alloc.destroy(p); +#if BOOST_CB_ENABLE_DEBUG + invalidate_iterators(is_invalid_condition(p)); + ::memset(p, cb_details::CB_Unitialized, sizeof(value_type)); +#endif + } + + //! Destroy the whole content of the circular buffer. + void destroy_content() { + for (size_type ii = 0; ii < size(); ++ii, increment(m_first)) + destroy_item(m_first); + } + + //! Destroy content and free allocated memory. + void destroy() { + destroy_content(); + deallocate(m_buff, capacity()); +#if BOOST_CB_ENABLE_DEBUG + invalidate_all_iterators(); // invalidate iterators pointing to end() + m_buff = 0; + m_first = 0; + m_last = 0; + m_end = 0; +#endif + } + + //! Specialized assign method. + template + void assign(InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) { + assign((size_type)n, item); + } + + //! Specialized assign method. + template + void assign(InputIterator first, InputIterator last, std::input_iterator_tag) { + BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + do_assign(std::distance(first, last), assign_range(first, last, m_alloc)); + } + + //! Helper assign method. + template + void do_assign(size_type n, const Functor& fnc) { + if (n > capacity()) { + pointer buff = allocate(n); + BOOST_CB_TRY + fnc(buff); + BOOST_CB_UNWIND(deallocate(buff, n)) + destroy(); + m_buff = buff; + m_end = m_buff + n; + } else { + destroy_content(); + BOOST_CB_TRY + fnc(m_buff); + BOOST_CB_UNWIND(m_size = 0) + } + m_size = n; + m_first = m_buff; + m_last = add(m_buff, size()); + } + + //! Specialized insert method. + template + void insert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) { + insert(pos, (size_type)n, item); + } + + //! Specialized insert method. + template + void insert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) { + BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + difference_type n = std::distance(first, last); + if (n == 0) + return; + difference_type copy = capacity() - (end() - pos); + if (copy == 0) + return; + if (n > copy) { + std::advance(first, n - copy); + n = copy; + } + insert_n_item(pos, n, iterator_wrapper(first)); + } + + //! Helper insert method. + template + void insert_n_item(iterator pos, size_type n, const Wrapper& wrapper) { + size_type construct = capacity() - size(); + if (construct > n) + construct = n; + if (pos.m_it == 0) { + size_type ii = 0; + pointer p = m_last; + BOOST_CB_TRY + for (; ii < construct; ++ii, increment(p)) + m_alloc.construct(p, *wrapper.get_reference()); + for (;ii < n; ++ii, increment(p)) + replace(p, *wrapper.get_reference()); + BOOST_CB_UNWIND( + size_type constructed = std::min(ii, construct); + m_last = add(m_last, constructed); + m_size += constructed; + if (ii >= construct) + tidy(p); + ) + } else { + pointer src = m_last; + pointer dest = add(m_last, n - 1); + size_type ii = 0; + BOOST_CB_TRY + while (src != pos.m_it) { + decrement(src); + create_or_replace(dest, *src); + decrement(dest); + } + for (dest = pos.m_it; ii < n; ++ii, increment(dest)) + create_or_replace(dest, *wrapper.get_reference()); + BOOST_CB_UNWIND( + for (pointer p1 = m_last, p2 = add(m_last, n - 1); p1 != src; decrement(p2)) { + decrement(p1); + destroy_created(p2); + } + for (n = 0, src = pos.m_it; n < ii; ++n, increment(src)) + destroy_created(src); + if (!is_uninitialized(dest)) + tidy(dest); + ) + } + m_last = add(m_last, n); + m_first = add(m_first, n - construct); + m_size += construct; + } + + //! Specialized rinsert method. + template + void rinsert(iterator pos, InputIterator n, InputIterator item, cb_details::cb_int_iterator_tag) { + rinsert(pos, (size_type)n, item); + } + + //! Specialized rinsert method. + template + void rinsert(iterator pos, InputIterator first, InputIterator last, std::input_iterator_tag) { + BOOST_CB_IS_CONVERTIBLE(InputIterator, value_type); + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + rinsert_n_item(pos, std::distance(first, last), iterator_wrapper(first)); + } + + //! Helper rinsert method. + template + void rinsert_n_item(iterator pos, size_type n, const Wrapper& wrapper) { + if (n == 0) + return; + size_type copy = capacity() - (pos - begin()); + if (copy == 0) + return; + if (n > copy) + n = copy; + size_type construct = capacity() - size(); + if (construct > n) + construct = n; + if (pos == begin()) { + pointer p = sub(map_pointer(pos.m_it), n); + size_type ii = n; + BOOST_CB_TRY + for (;ii > construct; --ii, increment(p)) + replace(p, *wrapper.get_reference()); + for (; ii > 0; --ii, increment(p)) + m_alloc.construct(p, *wrapper.get_reference()); + BOOST_CB_UNWIND( + size_type unwind = ii < construct ? construct - ii : 0; + pointer tmp = sub(map_pointer(pos.m_it), construct); + for (n = 0; n < unwind; ++n, increment(tmp)) + destroy_item(tmp); + if (ii > construct) + tidy(p); + ) + } else { + pointer src = m_first; + pointer dest = sub(m_first, n); + pointer p = map_pointer(pos.m_it); + size_type ii = 0; + BOOST_CB_TRY + while (src != p) { + create_or_replace(dest, *src); + increment(src); + increment(dest); + } + dest = sub(p, n); + for (; ii < n; ++ii, increment(dest)) + create_or_replace(dest, *wrapper.get_reference()); + BOOST_CB_UNWIND( + for (pointer p1 = m_first, p2 = sub(m_first, n); p1 != src; increment(p1), increment(p2)) + destroy_created(p2); + p = sub(p, n); + for (n = 0; n < ii; ++n, increment(p)) + destroy_created(p); + if (!is_uninitialized(dest)) + tidy(dest); + ) + } + m_first = sub(m_first, n); + m_last = sub(m_last, n - construct); + m_size += construct; + } +}; + +// Non-member functions + +//! Test two circular buffers for equality. +template +inline bool operator == (const circular_buffer& lhs, + const circular_buffer& rhs) { + return lhs.size() == rhs.size() && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +//! Lexicographical comparison. +template +inline bool operator < (const circular_buffer& lhs, + const circular_buffer& rhs) { + return std::lexicographical_compare( + lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) + +//! Test two circular buffers for non-equality. +template +inline bool operator != (const circular_buffer& lhs, + const circular_buffer& rhs) { + return !(lhs == rhs); +} + +//! Lexicographical comparison. +template +inline bool operator > (const circular_buffer& lhs, + const circular_buffer& rhs) { + return rhs < lhs; +} + +//! Lexicographical comparison. +template +inline bool operator <= (const circular_buffer& lhs, + const circular_buffer& rhs) { + return !(rhs < lhs); +} + +//! Lexicographical comparison. +template +inline bool operator >= (const circular_buffer& lhs, + const circular_buffer& rhs) { + return !(lhs < rhs); +} + +//! Swap the contents of two circular buffers. +template +inline void swap(circular_buffer& lhs, circular_buffer& rhs) { + lhs.swap(rhs); +} + +#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP) diff --git a/include/boost/circular_buffer/debug.hpp b/include/boost/circular_buffer/debug.hpp new file mode 100644 index 0000000..a367964 --- /dev/null +++ b/include/boost/circular_buffer/debug.hpp @@ -0,0 +1,211 @@ +// Debug support for the circular buffer library. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) +#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +namespace boost { + +namespace cb_details { + +#if BOOST_CB_ENABLE_DEBUG + +class cb_iterator_base; + +/*! + \class cb_iterator_registry + \brief Registry of valid iterators. + + This class is intended to be a base class of a container. +*/ +class cb_iterator_registry { + + //! Pointer to the chain of valid iterators. + mutable const cb_iterator_base* m_iterators; + +public: +// Methods + + //! Default constructor. + cb_iterator_registry() : m_iterators(0) {} + + //! Register an iterator into the list of valid iterators. + /*! + \note The method is const in order to register iterators into const containers, too. + */ + void register_iterator(const cb_iterator_base* it) const; // the implementation is below + + //! Unregister an iterator from the list of valid iterators. + /*! + \note The method is const in order to unregister iterators from const containers, too. + */ + void unregister_iterator(const cb_iterator_base* it) const; // the implementation is below + + //! Invalidate all iterators. + void invalidate_all_iterators(); // the implementation is below + + //! Invalidate every iterator conforming to the condition. + template + void invalidate_iterators(const Condition& condition) { + const cb_iterator_base* previous = 0; + for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) { + if (condition(p)) { + p->invalidate(); + remove(p, previous); + continue; + } + previous = p; + } + } + +private: +// Helpers + + //! Remove the current iterator from the iterator chain. + void remove(const cb_iterator_base* current, + const cb_iterator_base* previous) const; // the implementation is below +}; + +/*! + \class cb_iterator_base + \brief Registers/unregisters iterators into the registry of valid iterators. + + This class is intended to be a base class of an iterator. +*/ +class cb_iterator_base { + +private: +// Members + + //! Iterator registry. + mutable const cb_iterator_registry* m_registry; + + //! Next iterator in the iterator chain. + mutable const cb_iterator_base* m_next; + +public: +// Construction/destruction + + //! Default constructor. + cb_iterator_base() : m_registry(0), m_next(0) {} + + //! Constructor taking the iterator registry as a parameter. + cb_iterator_base(const cb_iterator_registry* registry) + : m_registry(registry), m_next(0) { + register_self(); + } + + //! Copy constructor. + cb_iterator_base(const cb_iterator_base& rhs) + : m_registry(rhs.m_registry), m_next(0) { + register_self(); + } + + //! Destructor. + ~cb_iterator_base() { unregister_self(); } + + //! Assign operator. + cb_iterator_base& operator = (const cb_iterator_base& rhs) { + if (m_registry == rhs.m_registry) + return *this; + unregister_self(); + m_registry = rhs.m_registry; + register_self(); + return *this; + } + +// Methods + + //! Is the iterator valid? + bool is_valid() const { return m_registry != 0; } + + //! Invalidate the iterator. + /*! + \note The method is const in order to invalidate const iterators, too. + */ + void invalidate() const { m_registry = 0; } + + //! Return the next iterator in the iterator chain. + const cb_iterator_base* next() const { return m_next; } + + //! Set the next iterator in the iterator chain. + /*! + \note The method is const in order to set a next iterator to a const iterator, too. + */ + void set_next(const cb_iterator_base* it) const { m_next = it; } + +private: +// Helpers + + //! Register self as a valid iterator. + void register_self() { + if (m_registry != 0) + m_registry->register_iterator(this); + } + + //! Unregister self from valid iterators. + void unregister_self() { + if (m_registry != 0) + m_registry->unregister_iterator(this); + } +}; + +inline void cb_iterator_registry::register_iterator(const cb_iterator_base* it) const { + it->set_next(m_iterators); + m_iterators = it; +} + +inline void cb_iterator_registry::unregister_iterator(const cb_iterator_base* it) const { + const cb_iterator_base* previous = 0; + for (const cb_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()); + remove(it, previous); +} + +inline void cb_iterator_registry::invalidate_all_iterators() { + for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) + p->invalidate(); + m_iterators = 0; +} + +inline void cb_iterator_registry::remove(const cb_iterator_base* current, + const cb_iterator_base* previous) const { + if (previous == 0) + m_iterators = m_iterators->next(); + else + previous->set_next(current->next()); +} + +#else // #if BOOST_CB_ENABLE_DEBUG + +class cb_iterator_registry { +#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000) + char dummy_; // BCB: by default empty structure has 8 bytes +#endif +}; + +class cb_iterator_base { +#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000) + char dummy_; // BCB: by default empty structure has 8 bytes +#endif + +public: + cb_iterator_base() {} + cb_iterator_base(const cb_iterator_registry*) {} +}; + +#endif // #if BOOST_CB_ENABLE_DEBUG + +} // namespace cb_details + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) diff --git a/include/boost/circular_buffer/details.hpp b/include/boost/circular_buffer/details.hpp new file mode 100644 index 0000000..5b83fca --- /dev/null +++ b/include/boost/circular_buffer/details.hpp @@ -0,0 +1,502 @@ +// Helper classes and functions for the circular buffer. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP) +#define BOOST_CIRCULAR_BUFFER_DETAILS_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include + +namespace boost { + +namespace cb_details { + +// The value the uninitialized memory is filled with. +const int CB_Unitialized = 0xcc; + +/*! + \struct cb_int_iterator_tag + \brief Identifying tag for integer types (not for iterators). +*/ +struct cb_int_iterator_tag { +#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000) + char dummy_; // BCB: by default empty structure has 8 bytes +#endif +}; + +/*! + \struct cb_iterator_category + \brief Defines iterator category. +*/ +template +struct cb_iterator_category { + //! Represents iterators. + typedef std::input_iterator_tag iterator_category; +}; + +template <> +struct cb_iterator_category { + //! Represents integral types (not iterators). + typedef cb_int_iterator_tag iterator_category; +}; + +/*! + \struct cb_iterator_category_traits + \brief Defines the iterator category tag for the given iterator. +*/ +template +struct cb_iterator_category_traits { + //! Iterator category tag type. + /*! + Depending on the template parameter the tag distinguishes + between iterators and non-iterators. If the template parameter + is an iterator, the tag is typedef for std::input_iterator_tag. + If the parameter is not an iterator, the tag is typedef for + cb_int_iterator_tag. + */ + typedef typename cb_details::cb_iterator_category< + is_integral::value>::iterator_category tag; +}; + +/*! + \struct cb_destroy_tag + \brief Identifying tag for types which have to be destroyed when replaced. +*/ +struct cb_destroy_tag { +#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000) + char dummy_; // BCB: by default empty structure has 8 bytes +#endif +}; + +/*! + \struct cb_assign_tag + \brief Identifying tag for types which do not have to be destroyed when replaced. +*/ +struct cb_assign_tag { +#if BOOST_WORKAROUND(__BORLANDC__, < 0x6000) + char dummy_; // BCB: by default empty structure has 8 bytes +#endif +}; + +/*! + \struct cb_replace_category + \brief Defines replace category for the given type. +*/ +template +struct cb_replace_category { + //! Represents types which have to be destroyed. + typedef cb_destroy_tag replace_category; +}; + +template <> +struct cb_replace_category { + //! Represents types which do not have to be destroyed. + typedef cb_assign_tag replace_category; +}; + +/*! + \struct cb_replace_category_traits + \brief Defines the replace category tag for the given type. +*/ +template +struct cb_replace_category_traits { + //! Replace category tag type. + /*! + Depending on the template parameter the tag distinguishes + between types which have to be destroyed (e.g. class) and types which + do not have to be (e.g. integral type) when replaced. + */ + typedef typename cb_details::cb_replace_category< + is_scalar::value>::replace_category tag; +}; + +template struct cb_nonconst_traits; + +/*! + \struct cb_const_traits + \brief Defines the data types for a const iterator. + \param Traits Defines the basic types. +*/ +template +struct cb_const_traits { + // Basic types + typedef typename Traits::value_type value_type; + typedef typename Traits::const_pointer pointer; + typedef typename Traits::const_reference reference; + typedef typename Traits::size_type size_type; + typedef typename Traits::difference_type difference_type; + + // Non-const traits + typedef cb_nonconst_traits nonconst_traits; +}; + +/*! + \struct cb_nonconst_traits + \brief Defines the data types for a non-const iterator. + \param Traits Defines the basic types. +*/ +template +struct cb_nonconst_traits { + // Basic types + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename Traits::size_type size_type; + typedef typename Traits::difference_type difference_type; + + // Non-const traits + typedef cb_nonconst_traits nonconst_traits; +}; + +/*! + \struct cb_helper_pointer + \brief Helper pointer used in the cb_iterator. +*/ +template +struct cb_helper_pointer { + bool m_end; + typename Traits0::pointer m_it; +}; + +/*! + \class cb_iterator + \brief Random access iterator for the circular buffer. + \param Buff The type of the underlying circular buffer. + \param Traits Defines basic iterator types. + \note This iterator is not circular. It was designed + for iterating from begin() to end() of the circular buffer. +*/ +template +class cb_iterator : + public boost::iterator< + std::random_access_iterator_tag, + typename Traits::value_type, + typename Traits::difference_type, + typename Traits::pointer, + typename Traits::reference>, + public cb_iterator_base +{ +private: + // Helper types + + //! Base iterator. + typedef boost::iterator< + std::random_access_iterator_tag, + typename Traits::value_type, + typename Traits::difference_type, + typename Traits::pointer, + typename Traits::reference> base_type; + + //! Non-const iterator. + typedef cb_iterator nonconst_self; + +public: +// Basic types + + //! The type of the elements stored in the circular buffer. + typedef typename base_type::value_type value_type; + + //! Pointer to the element. + typedef typename base_type::pointer pointer; + + //! Reference to the element. + typedef typename base_type::reference reference; + + //! Size type. + typedef typename Traits::size_type size_type; + + //! Difference type. + typedef typename base_type::difference_type difference_type; + +// Member variables + + //! The circular buffer where the iterator points to. + const Buff* m_buff; + + //! An internal iterator. + pointer m_it; + +// Construction & assignment + + // Default copy constructor. + + //! Default constructor. + cb_iterator() : m_buff(0), m_it(0) {} + + //! Copy constructor (used for converting from a non-const to a const iterator). + cb_iterator(const nonconst_self& it) : cb_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {} + + //! Internal constructor. + /*! + \note This constructor is not intended to be used directly by the user. + */ + cb_iterator(const Buff* cb, const pointer it) : cb_iterator_base(cb), m_buff(cb), m_it(it) {} + + // Assign operator. + cb_iterator& operator = (const cb_iterator& it) { + if (this == &it) + return *this; + cb_iterator_base::operator =(it); + m_buff = it.m_buff; + m_it = it.m_it; + return *this; + } + +// Random access iterator methods + + //! Dereferencing operator. + reference operator * () const { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() + return *m_it; + } + + //! Dereferencing operator. + pointer operator -> () const { return &(operator*()); } + + //! Difference operator. + difference_type operator - (const cb_iterator& it) const { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers + cb_helper_pointer lhs = create_helper_pointer(*this); + cb_helper_pointer rhs = create_helper_pointer(it); + if (less(rhs, lhs) && lhs.m_it <= rhs.m_it) + return lhs.m_it + m_buff->capacity() - rhs.m_it; + if (less(lhs, rhs) && lhs.m_it >= rhs.m_it) + return lhs.m_it - m_buff->capacity() - rhs.m_it; + return lhs.m_it - rhs.m_it; + } + + //! Increment operator (prefix). + cb_iterator& operator ++ () { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() + m_buff->increment(m_it); + if (m_it == m_buff->m_last) + m_it = 0; + return *this; + } + + //! Increment operator (postfix). + cb_iterator operator ++ (int) { + cb_iterator tmp = *this; + ++*this; + return tmp; + } + + //! Decrement operator (prefix). + cb_iterator& operator -- () { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin() + if (m_it == 0) + m_it = m_buff->m_last; + m_buff->decrement(m_it); + return *this; + } + + //! Decrement operator (postfix). + cb_iterator operator -- (int) { + cb_iterator tmp = *this; + --*this; + return tmp; + } + + //! Iterator addition. + cb_iterator& operator += (difference_type n) { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + if (n > 0) { + BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n + m_it = m_buff->add(m_it, n); + if (m_it == m_buff->m_last) + m_it = 0; + } else if (n < 0) { + *this -= -n; + } + return *this; + } + + //! Iterator addition. + cb_iterator operator + (difference_type n) const { return cb_iterator(*this) += n; } + + //! Iterator subtraction. + cb_iterator& operator -= (difference_type n) { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + if (n > 0) { + BOOST_CB_ASSERT(m_buff->begin() - *this <= -n); // check for too large n + m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n); + } else if (n < 0) { + *this += -n; + } + return *this; + } + + //! Iterator subtraction. + cb_iterator operator - (difference_type n) const { return cb_iterator(*this) -= n; } + + //! Element access operator. + reference operator [] (difference_type n) const { return *(*this + n); } + +// Equality & comparison + + //! Equality. + template + bool operator == (const cb_iterator& it) const { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers + return m_it == it.m_it; + } + + //! Inequality. + template + bool operator != (const cb_iterator& it) const { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers + return m_it != it.m_it; + } + + //! Less. + template + bool operator < (const cb_iterator& it) const { + BOOST_CB_ASSERT(is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid()); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_buff == it.m_buff); // check for iterators of different containers + return less(create_helper_pointer(*this), create_helper_pointer(it)); + } + + //! Greater. + template + bool operator > (const cb_iterator& it) const { return it < *this; } + + //! Less or equal. + template + bool operator <= (const cb_iterator& it) const { return !(it < *this); } + + //! Greater or equal. + template + bool operator >= (const cb_iterator& it) const { return !(*this < it); } + +private: +// Helpers + + //! Create helper pointer. + template + cb_helper_pointer create_helper_pointer(const cb_iterator& it) const { + cb_helper_pointer helper; + helper.m_end = (it.m_it == 0); + helper.m_it = helper.m_end ? m_buff->m_last : it.m_it; + return helper; + } + + //! Compare two pointers. + /*! + \return 1 if p1 is greater than p2. + \return 0 if p1 is equal to p2. + \return -1 if p1 is lower than p2. + */ + template + static difference_type compare(Pointer0 p1, Pointer1 p2) { + return p1 < p2 ? -1 : (p1 > p2 ? 1 : 0); + } + + //! Less. + template + bool less(const InternalIterator0& lhs, const InternalIterator1& rhs) const { + switch (compare(lhs.m_it, m_buff->m_first)) { + case -1: + switch (compare(rhs.m_it, m_buff->m_first)) { + case -1: return lhs.m_it < rhs.m_it; + case 0: return rhs.m_end; + case 1: return false; + } + case 0: + switch (compare(rhs.m_it, m_buff->m_first)) { + case -1: return !lhs.m_end; + case 0: return !lhs.m_end && rhs.m_end; + case 1: return !lhs.m_end; + } + case 1: + switch (compare(rhs.m_it, m_buff->m_first)) { + case -1: return true; + case 0: return rhs.m_end; + case 1: return lhs.m_it < rhs.m_it; + } + } + return false; + } +}; + +//! Iterator addition. +template +inline cb_iterator +operator + (typename Traits::difference_type n, const cb_iterator& it) { + return it + n; +} + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) + +//! Iterator category. +template +inline std::random_access_iterator_tag iterator_category(const cb_iterator&) { + return std::random_access_iterator_tag(); +} + +//! The type of the elements stored in the circular buffer. +template +inline typename Traits::value_type* value_type(const cb_iterator&) { return 0; } + +//! Distance type. +template +inline typename Traits::difference_type* distance_type(const cb_iterator&) { return 0; } + +#endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) + +/*! + \fn FwdIterator uninitialized_copy(InputIterator first, InputIterator last, FwdIterator dest, Alloc& alloc) + \brief Equivalent of std::uninitialized_copy with allocator. +*/ +template +inline FwdIterator uninitialized_copy(InputIterator first, InputIterator last, FwdIterator dest, Alloc& alloc) { + FwdIterator next = dest; + BOOST_CB_TRY + for (; first != last; ++first, ++dest) + alloc.construct(dest, *first); + BOOST_CB_UNWIND( + for (; next != dest; ++next) + alloc.destroy(next); + ) + return dest; +} + +/*! + \fn void uninitialized_fill_n(FwdIterator first, Diff n, const T& item, Alloc& alloc) + \brief Equivalent of std::uninitialized_fill_n with allocator. +*/ +template +inline void uninitialized_fill_n(FwdIterator first, Diff n, const T& item, Alloc& alloc) { + FwdIterator next = first; + BOOST_CB_TRY + for (; n > 0; ++first, --n) + alloc.construct(first, item); + BOOST_CB_UNWIND( + for (; next != first; ++next) + alloc.destroy(next); + ) +} + +} // namespace cb_details + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP) diff --git a/include/boost/circular_buffer_fwd.hpp b/include/boost/circular_buffer_fwd.hpp new file mode 100644 index 0000000..79e64f3 --- /dev/null +++ b/include/boost/circular_buffer_fwd.hpp @@ -0,0 +1,41 @@ +// Forward declaration of the circular buffer and its adaptor. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) +#define BOOST_CIRCULAR_BUFFER_FWD_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#if !defined(BOOST_NO_STD_ALLOCATOR) + #include +#else + #include +#endif + +namespace boost { + +#if !defined(BOOST_NO_STD_ALLOCATOR) + #define BOOST_CB_DEFAULT_ALLOCATOR(T) std::allocator +#else + #define BOOST_CB_DEFAULT_ALLOCATOR(T) BOOST_DEDUCED_TYPENAME std::vector::allocator_type +#endif + +template +class circular_buffer; + +template +class circular_buffer_space_optimized; + +#undef BOOST_CB_DEFAULT_ALLOCATOR + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) diff --git a/index.html b/index.html new file mode 100644 index 0000000..fcd305c --- /dev/null +++ b/index.html @@ -0,0 +1,10 @@ + + + + + + + + Automatic redirection failed, please go to circular_buffer.html. + + diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 0000000..32fba75 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,17 @@ +# Boost circular_buffer test Jamfile. + +subproject libs/circular_buffer/test ; + +# Bring in rules for testing. +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; + +# Make tests run by default. +DEPENDS all : circular_buffer ; + +{ + test-suite "circular_buffer" + : [ run base_test.cpp ] + [ run adaptor_test.cpp ] + ; +} diff --git a/test/adaptor_test.cpp b/test/adaptor_test.cpp new file mode 100644 index 0000000..7567b4a --- /dev/null +++ b/test/adaptor_test.cpp @@ -0,0 +1,75 @@ +// Test of the adaptor of the circular buffer. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_CB_TEST + +#include "test.hpp" +#include + +using namespace boost; +using namespace std; +using unit_test_framework::test_suite; + +#define CB_CONTAINER circular_buffer_space_optimized +#define CB_MIN_CAPACITY ,0 + +#include "common.cpp" + +// min_capacity test (it is useful to use any debug tool) +void min_capacity_test() { + + vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + + circular_buffer_space_optimized cb1(10, 10); + circular_buffer_space_optimized cb2(10, 5, 1); + circular_buffer_space_optimized cb3(20, 10, v.begin(), v.end()); + + BOOST_CHECK(cb1.size() == 0); + BOOST_CHECK(cb1.capacity() == 10); + BOOST_CHECK(cb1.min_capacity() == 10); + BOOST_CHECK(cb2[0] == 1); + BOOST_CHECK(cb2.size() == 10); + BOOST_CHECK(cb2.capacity() == 10); + BOOST_CHECK(cb2.min_capacity() == 5); + BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3.size() == 5); + BOOST_CHECK(cb3.capacity() == 20); + BOOST_CHECK(cb3.min_capacity() == 10); + BOOST_CHECK(cb1.min_capacity() <= cb1.internal_capacity()); + BOOST_CHECK(cb2.min_capacity() <= cb2.internal_capacity()); + BOOST_CHECK(cb3.min_capacity() <= cb3.internal_capacity()); + + cb2.erase(cb2.begin() + 2, cb2.end()); + + BOOST_CHECK(cb2.size() == 2); + BOOST_CHECK(cb2.min_capacity() <= cb2.internal_capacity()); + + cb2.clear(); + cb3.clear(); + + BOOST_CHECK(cb2.empty()); + BOOST_CHECK(cb3.empty()); + BOOST_CHECK(cb2.min_capacity() <= cb2.internal_capacity()); + BOOST_CHECK(cb3.min_capacity() <= cb3.internal_capacity()); +} + +// test main +test_suite* init_unit_test_suite(int argc, char * argv[]) { + + test_suite* tests = BOOST_TEST_SUITE("Unit tests for the circular_buffer_space_optimized."); + add_common_tests(tests); + + tests->add(BOOST_TEST_CASE(&min_capacity_test)); + + return tests; +} diff --git a/test/base_test.cpp b/test/base_test.cpp new file mode 100644 index 0000000..08d5e2b --- /dev/null +++ b/test/base_test.cpp @@ -0,0 +1,493 @@ +// Test of the base circular buffer container. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "test.hpp" +#include + +using namespace boost; +using namespace std; +using unit_test_framework::test_suite; + +#define CB_CONTAINER circular_buffer +#define CB_MIN_CAPACITY /* none */ + +#include "common.cpp" + +void iterator_constructor_and_assign_test() { + + circular_buffer cb(4, 3); + circular_buffer::iterator it = cb.begin(); + circular_buffer::iterator itCopy; + itCopy = it; + it = it; + circular_buffer::const_iterator cit; + cit = it; + circular_buffer::const_iterator end1 = cb.end(); + circular_buffer::const_iterator end2 = end1; + + BOOST_CHECK(itCopy == it); + BOOST_CHECK(cit == it); + BOOST_CHECK(end1 == end2); + BOOST_CHECK(it != end1); + BOOST_CHECK(cit != end2); +} + +void iterator_reference_test() { + + circular_buffer cb(3, C()); + circular_buffer::iterator it = cb.begin(); + circular_buffer::const_iterator cit = cb.begin() + 1; + + BOOST_CHECK((*it).test_reference1() == it->test_reference2()); + BOOST_CHECK((*cit).test_reference2() == cit->test_reference1()); +} + +void iterator_difference_test() { + + circular_buffer cb(5, 1); + cb.push_back(2); + circular_buffer::iterator it1 = cb.begin() + 2; + circular_buffer::iterator it2 = cb.begin() + 3; + circular_buffer::const_iterator begin = cb.begin(); + circular_buffer::iterator end = cb.end(); + + BOOST_CHECK(begin - begin == 0); + BOOST_CHECK(end - cb.begin() == 5); + BOOST_CHECK(end - end == 0); + BOOST_CHECK(begin - cb.end() == -5); + BOOST_CHECK(it1 - cb.begin() == 2); + BOOST_CHECK(end - it1 == 3); + BOOST_CHECK(it2 - it1 == 1); + BOOST_CHECK(it1 - it2 == -1); + BOOST_CHECK(it2 - it2 == 0); +} + +void iterator_increment_test() { + + circular_buffer cb(10, 1); + cb.push_back(2); + circular_buffer::iterator it1 = cb.begin(); + circular_buffer::iterator it2 = cb.begin() + 5; + circular_buffer::iterator it3 = cb.begin() + 9; + it1++; + it2++; + ++it3; + + BOOST_CHECK(it1 == cb.begin() + 1); + BOOST_CHECK(it2 == cb.begin() + 6); + BOOST_CHECK(it3 == cb.end()); +} + +void iterator_decrement_test() { + + circular_buffer cb(10, 1); + cb.push_back(2); + circular_buffer::iterator it1= cb.end(); + circular_buffer::iterator it2= cb.end() - 5; + circular_buffer::iterator it3= cb.end() - 9; + --it1; + it2--; + --it3; + + BOOST_CHECK(it1 == cb.end() - 1); + BOOST_CHECK(it2 == cb.end() - 6); + BOOST_CHECK(it3 == cb.begin()); +} + +void iterator_addition_test() { + + circular_buffer cb(10, 1); + cb.push_back(2); + cb.push_back(2); + circular_buffer::iterator it1 = cb.begin() + 2; + circular_buffer::iterator it2 = cb.end(); + circular_buffer::iterator it3 = cb.begin() + 5; + circular_buffer::iterator it4 = cb.begin() + 9; + it1 += 3; + it2 += 0; + it3 += 5; + it4 += -2; + + BOOST_CHECK(it1 == 5 + cb.begin()); + BOOST_CHECK(it2 == cb.end()); + BOOST_CHECK(it3 == cb.end()); + BOOST_CHECK(it4 + 3 == cb.end()); + BOOST_CHECK((-3) + it4 == cb.begin() + 4); + BOOST_CHECK(cb.begin() + 0 == cb.begin()); +} + +void iterator_subtraction_test() { + + circular_buffer cb(10, 1); + cb.push_back(2); + cb.push_back(2); + cb.push_back(2); + circular_buffer::iterator it1 = cb.begin(); + circular_buffer::iterator it2 = cb.end(); + circular_buffer::iterator it3 = cb.end() - 5; + circular_buffer::iterator it4 = cb.begin() + 7; + it1 -= -2; + it2 -= 0; + it3 -= 5; + + BOOST_CHECK(it1 == cb.begin() + 2); + BOOST_CHECK(it2 == cb.end()); + BOOST_CHECK(it3 == cb.begin()); + BOOST_CHECK(it4 - 7 == cb.begin()); + BOOST_CHECK(it4 - (-3) == cb.end()); + BOOST_CHECK(cb.begin() - 0 == cb.begin()); +} + +void iterator_element_access_test() { + + circular_buffer cb(10); + cb.push_back(1); + cb.push_back(2); + cb.push_back(3); + cb.push_back(4); + cb.push_back(5); + cb.push_back(6); + circular_buffer::iterator it = cb.begin() + 1; + + BOOST_CHECK(it[0] == 2); + BOOST_CHECK(it[-1] == 1); + BOOST_CHECK(it[2] == 4); +} + +void iterator_comparison_test() { + + circular_buffer cb(5, 1); + cb.push_back(2); + circular_buffer::iterator it = cb.begin() + 2; + circular_buffer::const_iterator begin = cb.begin(); + circular_buffer::iterator end = cb.end(); + + BOOST_CHECK(begin == begin); + BOOST_CHECK(end > cb.begin()); + BOOST_CHECK(begin < end); + BOOST_CHECK(end > begin); + BOOST_CHECK(end == end); + BOOST_CHECK(begin < cb.end()); + BOOST_CHECK(!(begin + 1 > cb.end())); + BOOST_CHECK(it > cb.begin()); + BOOST_CHECK(end > it); + BOOST_CHECK(begin >= begin); + BOOST_CHECK(end >= cb.begin()); + BOOST_CHECK(end <= end); + BOOST_CHECK(begin <= cb.end()); + BOOST_CHECK(it >= cb.begin()); + BOOST_CHECK(end >= it); + BOOST_CHECK(!(begin + 4 < begin + 4)); + BOOST_CHECK(begin + 4 < begin + 5); + BOOST_CHECK(!(begin + 5 < begin + 4)); + BOOST_CHECK(it < end - 1); + BOOST_CHECK(!(end - 1 < it)); +} + +void iterator_invalidation_test() { + +#if !defined(NDEBUG) && !defined(BOOST_DISABLE_CB_DEBUG) + + circular_buffer::iterator it1; + circular_buffer::const_iterator it2; + circular_buffer::iterator it3; + circular_buffer::const_iterator it4; + circular_buffer::const_iterator it5; + + BOOST_CHECK(!it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(!it3.is_valid()); + BOOST_CHECK(!it4.is_valid()); + BOOST_CHECK(!it5.is_valid()); + + { + circular_buffer cb(5, 0); + const circular_buffer ccb(5, 0); + + it1 = cb.begin(); + it2 = ccb.end(); + it3 = it1; + it4 = it1; + it5 = it2; + + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(it2.is_valid()); + BOOST_CHECK(it3.is_valid()); + BOOST_CHECK(it4.is_valid()); + BOOST_CHECK(it5.is_valid()); + } + + BOOST_CHECK(!it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(!it3.is_valid()); + BOOST_CHECK(!it4.is_valid()); + BOOST_CHECK(!it5.is_valid()); + + circular_buffer cb1(10, 0); + circular_buffer cb2(20, 0); + it1 = cb1.end(); + it2 = cb2.begin(); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(it2.is_valid()); + + cb1.swap(cb2); + BOOST_CHECK(!it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + + it1 = cb1.begin() + 3; + it2 = cb1.begin(); + cb1.push_back(1); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(*it2.m_it == 1); + + circular_buffer cb3(5); + cb3.push_back(1); + cb3.push_back(2); + cb3.push_back(3); + cb3.push_back(4); + cb3.push_back(5); + it1 = cb3.begin() + 2; + it2 = cb3.begin(); + cb3.insert(cb3.begin() + 3, 6); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(*it2.m_it == 5); + + it1 = cb3.begin() + 3; + it2 = cb3.end() - 1; + cb3.push_front(7); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(*it2.m_it == 7); + + circular_buffer cb4(5); + cb4.push_back(1); + cb4.push_back(2); + cb4.push_back(3); + cb4.push_back(4); + cb4.push_back(5); + it1 = cb4.begin() + 3; + it2 = cb4.begin(); + cb4.rinsert(cb4.begin() + 2, 6); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + BOOST_CHECK(*it2.m_it == 2); + + it1 = cb1.begin() + 5; + it2 = cb1.end() - 1; + cb1.pop_back(); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + + it1 = cb1.begin() + 5; + it2 = cb1.begin(); + cb1.pop_front(); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + + circular_buffer cb5(20, 0); + it1 = cb5.begin() + 5; + it2 = cb5.begin() + 15; + cb5.erase(cb5.begin() + 10); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + + it1 = cb5.begin() + 1; + it2 = cb5.begin() + 8; + cb5.erase(cb5.begin() + 3, cb5.begin() + 7); + BOOST_CHECK(it1.is_valid()); + BOOST_CHECK(!it2.is_valid()); + +#endif // #if !defined(NDEBUG) && !defined(BOOST_DISABLE_CB_DEBUG) +} + +// basic exception safety test (it is useful to use any memory-leak detection tool) +void exception_safety_test() { + +#if !defined(BOOST_NO_EXCEPTIONS) + + circular_buffer cb1(3, 5); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb1.set_capacity(5), exception); + + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(circular_buffer cb2(5, 10), exception); + + circular_buffer cb3(5, 10); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(circular_buffer cb4(cb3), exception); + + vector v(5, 10); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(circular_buffer cb5(8, v.begin(), v.end()), exception); + + circular_buffer cb6(5, 10); + circular_buffer cb7(8, 3); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb7 = cb6, exception); + + circular_buffer cb8(5, 10); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb8.push_front(1), exception); + + circular_buffer cb9(5); + cb9.push_back(1); + cb9.push_back(2); + cb9.push_back(3); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb9.insert(cb9.begin() + 1, 4), exception); + + circular_buffer cb10(5); + cb10.push_back(1); + cb10.push_back(2); + cb10.push_back(3); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb10.rinsert(cb10.begin() + 1, 4), exception); + + circular_buffer cb11(5); + cb11.push_back(1); + cb11.push_back(2); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb11.rinsert(cb11.begin(), 1), exception); + + circular_buffer cb12(5, 1); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb12.assign(4, 2), exception); + + circular_buffer cb13(5, 1); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb13.assign(6, 2), exception); + + circular_buffer cb14(5); + cb14.push_back(1); + cb14.push_back(2); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb14.insert(cb14.begin(), 10, 3), exception); + + circular_buffer cb15(5); + cb15.push_back(1); + cb15.push_back(2); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb15.insert(cb15.end(), 10, 3), exception); + + circular_buffer cb16(5); + cb16.push_back(1); + cb16.push_back(2); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb16.rinsert(cb16.begin(), 10, 3), exception); + + circular_buffer cb17(5); + cb17.push_back(1); + cb17.push_back(2); + Integer::set_exception_trigger(3); + BOOST_CHECK_THROW(cb17.rinsert(cb17.end(), 10, 3), exception); + + circular_buffer cb18(5, 0); + cb18.push_back(1); + cb18.push_back(2); + cb18.pop_front(); + Integer::set_exception_trigger(4); + BOOST_CHECK_THROW(cb18.data(), exception); + + circular_buffer cb19(5, 0); + cb19.push_back(1); + cb19.push_back(2); + Integer::set_exception_trigger(5); + BOOST_CHECK_THROW(cb19.data(), exception); + + circular_buffer cb20(5, 0); + cb20.push_back(1); + cb20.push_back(2); + Integer::set_exception_trigger(6); + BOOST_CHECK_THROW(cb20.data(), exception); + + circular_buffer cb21(5); + cb21.push_back(1); + cb21.push_back(2); + cb21.push_back(3); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb21.insert(cb21.begin() + 1, 4), exception); + + circular_buffer cb22(5); + cb22.push_back(1); + cb22.push_back(2); + cb22.push_back(3); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb22.insert(cb22.end(), 4), exception); + + circular_buffer cb23(5, 0); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb23.insert(cb23.begin() + 1, 4), exception); + + circular_buffer cb24(5); + cb24.push_back(1); + cb24.push_back(2); + cb24.push_back(3); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb24.rinsert(cb24.begin() + 1, 4), exception); + + circular_buffer cb25(5, 0); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb25.rinsert(cb25.begin() + 3, 4), exception); + + circular_buffer cb26(5); + cb26.push_back(1); + cb26.push_back(2); + Integer::set_exception_trigger(5); + BOOST_CHECK_THROW(cb26.insert(cb26.begin(), 10, 3), exception); + + circular_buffer cb27(5); + cb27.push_back(1); + cb27.push_back(2); + Integer::set_exception_trigger(5); + BOOST_CHECK_THROW(cb27.insert(cb27.end(), 10, 3), exception); + + circular_buffer cb28(5); + cb28.push_back(1); + cb28.push_back(2); + Integer::set_exception_trigger(5); + BOOST_CHECK_THROW(cb28.rinsert(cb28.begin(), 10, 3), exception); + + circular_buffer cb29(5); + cb29.push_back(1); + cb29.push_back(2); + Integer::set_exception_trigger(5); + BOOST_CHECK_THROW(cb29.rinsert(cb29.end(), 10, 3), exception); + + circular_buffer cb30(10); + cb30.push_back(1); + cb30.push_back(2); + cb30.push_back(3); + Integer::set_exception_trigger(2); + BOOST_CHECK_THROW(cb30.rinsert(cb30.begin(), 10, 3), exception); + +#endif // #if !defined(BOOST_NO_EXCEPTIONS) +} + +// test main +test_suite* init_unit_test_suite(int argc, char * argv[]) { + + test_suite* tests = BOOST_TEST_SUITE("Unit tests for the circular_buffer."); + + add_common_tests(tests); + + tests->add(BOOST_TEST_CASE(&iterator_constructor_and_assign_test)); + tests->add(BOOST_TEST_CASE(&iterator_reference_test)); + tests->add(BOOST_TEST_CASE(&iterator_difference_test)); + tests->add(BOOST_TEST_CASE(&iterator_increment_test)); + tests->add(BOOST_TEST_CASE(&iterator_decrement_test)); + tests->add(BOOST_TEST_CASE(&iterator_addition_test)); + tests->add(BOOST_TEST_CASE(&iterator_subtraction_test)); + tests->add(BOOST_TEST_CASE(&iterator_element_access_test)); + tests->add(BOOST_TEST_CASE(&iterator_comparison_test)); + tests->add(BOOST_TEST_CASE(&iterator_invalidation_test)); + tests->add(BOOST_TEST_CASE(&exception_safety_test)); + + return tests; +} diff --git a/test/common.cpp b/test/common.cpp new file mode 100644 index 0000000..203cd70 --- /dev/null +++ b/test/common.cpp @@ -0,0 +1,1010 @@ +// Common tests for the circular buffer and its adaptor. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +void basic_test() { + + vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + v.push_back(6); + v.push_back(7); + CB_CONTAINER cb1(3 CB_MIN_CAPACITY, v.begin(), v.end()); + CB_CONTAINER cb2(10 CB_MIN_CAPACITY, v.begin(), v.end()); + CB_CONTAINER cb3(7 CB_MIN_CAPACITY, v.begin(), v.end()); + + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1.capacity() == 3); + BOOST_CHECK(cb1.size() == 3); + BOOST_CHECK(cb1[0] == 5); + BOOST_CHECK(cb1[2] == 7); + BOOST_CHECK(!cb2.full()); + BOOST_CHECK(cb2[2] == 3); + BOOST_CHECK(cb3.full()); + BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3[6] == 7); +} + +void constructor_and_element_access_test() { + + CB_CONTAINER cb(5 CB_MIN_CAPACITY, 3); + cb[1] = 10; + + BOOST_CHECK(cb.full()); + BOOST_CHECK(cb[1] == 10); + BOOST_CHECK(cb[4] == 3); +} + +void size_test() { + + CB_CONTAINER cb(3); + cb.push_back(1); + cb.push_back(2); + cb.push_back(3); + cb.push_back(4); + + BOOST_CHECK(cb.size() == 3); + BOOST_CHECK(cb.max_size() == cb.get_allocator().max_size()); +} + +void boundary_capacity_test() { + + CB_CONTAINER cb(0); + cb.push_back(1); + + BOOST_CHECK(cb.size() == 0); + BOOST_CHECK(cb.full()); + BOOST_CHECK(cb.empty()); +} + +void begin_and_end_test() { + + CB_CONTAINER cb1(10); + cb1.push_back(1); + cb1.push_back(2); + cb1.insert(cb1.begin(), 3); + int i = 0; + CB_CONTAINER::const_iterator it = cb1.begin(); + for (; it != cb1.end(); it++) { + i += *it; + } + CB_CONTAINER cb2(20); + + BOOST_CHECK(i == 6); + BOOST_CHECK(cb2.begin() == cb2.end()); +} + +void rbegin_and_rend_test() { + + CB_CONTAINER cb1(3); + cb1.push_back(1); + cb1.push_back(2); + cb1.insert(cb1.begin(), 3); + cb1.push_back(1); + int i = 0; + CB_CONTAINER::reverse_iterator it = cb1.rbegin(); + for (; it != cb1.rend(); it++) { + i += *it; + } + CB_CONTAINER cb2(20); + + BOOST_CHECK(i == 4); + BOOST_CHECK(cb2.rbegin() == cb2.rend()); +} + +void element_access_and_insert_test() { + + CB_CONTAINER cb(3); + cb.push_back(1); + cb.push_back(2); + cb.insert(cb.begin(), 3); + cb.push_back(4); + const CB_CONTAINER ccb(3 CB_MIN_CAPACITY, 2); + + BOOST_CHECK(cb[0] == 1); + BOOST_CHECK(cb[1] == 2); + BOOST_CHECK(cb[2] == 4); + BOOST_CHECK(ccb[2] == 2); +} + +void at_test() { + +#if !defined(BOOST_NO_EXCEPTIONS) + + CB_CONTAINER cb(3); + cb.push_back(1); + + try { + BOOST_CHECK(cb.at(0) == 1); + } + catch (out_of_range&) { + BOOST_ERROR("An unexpected exception has been thrown!"); + } + + BOOST_CHECK_THROW(cb.at(2), out_of_range); + +#endif // #if !defined(BOOST_NO_EXCEPTIONS) +} + +void front_and_back_test() { + + CB_CONTAINER cb(1); + cb.push_back(2); + cb.push_back(3); + + BOOST_CHECK(cb.front() == cb.back()); + BOOST_CHECK(cb.back() == 3); +} + +void data_test() { + + CB_CONTAINER cb1(10 CB_MIN_CAPACITY, 0); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + CB_CONTAINER cb2(10 CB_MIN_CAPACITY, 0); + cb2.push_back(1); + cb2.push_back(2); + cb2.push_back(3); + cb2.push_back(4); + cb2.push_back(5); + cb2.push_back(6); + cb2.push_back(7); + CB_CONTAINER cb3(10 CB_MIN_CAPACITY, 0); + cb3.push_back(1); + cb3.push_back(2); + cb3.push_back(3); + cb3.pop_front(); + cb3.pop_front(); + CB_CONTAINER cb4(5 CB_MIN_CAPACITY, 0); + cb4.push_back(1); + cb4.push_back(2); + cb4.data(); + CB_CONTAINER cb5(5); + + BOOST_CHECK(*cb1.data() == 0); + BOOST_CHECK(*(cb1.data() + 1) == 0); + BOOST_CHECK(*(cb1.data() + 7) == 1); + BOOST_CHECK(*(cb1.data() + 8) == 2); + BOOST_CHECK(*(cb1.data() + 9) == 3); + BOOST_CHECK(*cb2.data() == 0); + BOOST_CHECK(*(cb2.data() + 1) == 0); + BOOST_CHECK(*(cb2.data() + 2) == 0); + BOOST_CHECK(*(cb2.data() + 3) == 1); + BOOST_CHECK(*(cb2.data() + 4) == 2); + BOOST_CHECK(*(cb2.data() + 5) == 3); + BOOST_CHECK(*(cb2.data() + 6) == 4); + BOOST_CHECK(*(cb2.data() + 7) == 5); + BOOST_CHECK(*(cb2.data() + 8) == 6); + BOOST_CHECK(*(cb2.data() + 9) == 7); + BOOST_CHECK(*cb3.data() == 0); + BOOST_CHECK(*(cb3.data() + 1) == 0); + BOOST_CHECK(*(cb3.data() + 2) == 0); + BOOST_CHECK(*(cb3.data() + 3) == 0); + BOOST_CHECK(*(cb3.data() + 4) == 0); + BOOST_CHECK(*(cb3.data() + 5) == 1); + BOOST_CHECK(*(cb3.data() + 6) == 2); + BOOST_CHECK(*(cb3.data() + 7) == 3); + BOOST_CHECK(&cb4[0] < &cb4[1] && &cb4[1] < &cb4[2] && &cb4[2] < &cb4[3] && &cb4[3] < &cb4[4]); + BOOST_CHECK(cb5.data() == 0); +} + +void capacity_test() { + + CB_CONTAINER cb1(0); + CB_CONTAINER cb2(1); + + BOOST_CHECK(cb1.capacity() == 0); + BOOST_CHECK(cb2.capacity() == 1); +} + +void full_and_empty_test() { + + CB_CONTAINER cb1(10); + CB_CONTAINER cb2(3); + CB_CONTAINER cb3(2); + CB_CONTAINER cb4(2); + cb2.push_back(1); + cb2.push_back(3); + cb2.push_back(1); + cb2.push_back(1); + cb2.push_back(1); + cb3.push_back(3); + cb3.push_back(1); + cb4.push_back(1); + + BOOST_CHECK(cb1.empty()); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb3.full()); + BOOST_CHECK(!cb4.empty()); + BOOST_CHECK(!cb4.full()); +} + +void set_capacity_test() { + + CB_CONTAINER cb1(10); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(1); + cb1.set_capacity(5); + CB_CONTAINER cb2(3); + cb2.push_back(2); + cb2.push_back(3); + cb2.push_back(1); + cb2.set_capacity(10); + CB_CONTAINER cb3(5); + cb3.push_back(2); + cb3.push_back(3); + cb3.push_back(1); + cb3.set_capacity(2); + cb3.set_capacity(2); + CB_CONTAINER cb4(10); + cb4.push_back(2); + cb4.push_back(3); + cb4.push_back(1); + cb4.set_capacity(2, false); + + BOOST_CHECK(cb1.size() == 3); + BOOST_CHECK(cb1[0] == 2); + BOOST_CHECK(cb1.capacity() == 5); + BOOST_CHECK(cb2.size() == 3); + BOOST_CHECK(cb2[0] == 2); + BOOST_CHECK(cb2.capacity() == 10); + BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3[0] == 3); + BOOST_CHECK(cb3.capacity() == 2); + BOOST_CHECK(cb4.size() == 2); + BOOST_CHECK(cb4[0] == 2); + BOOST_CHECK(cb4.capacity() == 2); +} + +void resize_test() { + + CB_CONTAINER cb1(10); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + cb1.resize(20, 5); + CB_CONTAINER cb2(10); + cb2.push_back(1); + cb2.push_back(2); + cb2.push_back(3); + cb2.push_back(4); + cb2.resize(2); + CB_CONTAINER cb3(10); + cb3.push_back(1); + cb3.push_back(2); + cb3.push_back(3); + cb3.push_back(4); + cb3.resize(2, Integer(), false); + CB_CONTAINER cb4(10 CB_MIN_CAPACITY, 1); + cb4.resize(0); + CB_CONTAINER cb5(10 CB_MIN_CAPACITY, 1); + cb5.resize(10); + + BOOST_CHECK(cb1.size() == 20); + BOOST_CHECK(cb1.capacity() == 20); + BOOST_CHECK(cb1[0] == 1); + BOOST_CHECK(cb1[3] == 4); + BOOST_CHECK(cb1[4] == 5); + BOOST_CHECK(cb1[19] == 5); + BOOST_CHECK(cb2.size() == 2); + BOOST_CHECK(cb2.capacity() == 10); + BOOST_CHECK(cb2[0] == 3); + BOOST_CHECK(cb2[1] == 4); + BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3.capacity() == 10); + BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3[1] == 2); + BOOST_CHECK(cb4.size() == 0); + BOOST_CHECK(cb4.capacity() == 10); + BOOST_CHECK(cb5.size() == 10); + BOOST_CHECK(cb5.capacity() == 10); + BOOST_CHECK(cb5[0] == 1); + BOOST_CHECK(cb5[9] == 1); +} + +void constructor_test() { + + CB_CONTAINER cb1(3); + CB_CONTAINER cb2(3 CB_MIN_CAPACITY, 2); + + BOOST_CHECK(cb1.size() == 0); + BOOST_CHECK(cb1.capacity() == 3); + BOOST_CHECK(cb2[0] == 2); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb2[0] == 2); + BOOST_CHECK(cb2[1] == 2); + BOOST_CHECK(cb2[2] == 2); +} + +void assign_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + cb1.push_back(5); + cb1.assign(3, 8); + BOOST_CHECK(cb1.size() == 3); + BOOST_CHECK(cb1.capacity() == 4); + BOOST_CHECK(cb1[0] == 8); + BOOST_CHECK(cb1[2] == 8); + + cb1.assign(6, 7); + BOOST_CHECK(cb1.size() == 6); + BOOST_CHECK(cb1.capacity() == 6); + BOOST_CHECK(cb1[0] == 7); + BOOST_CHECK(cb1[5] == 7); + + CB_CONTAINER cb2(4); + cb2.assign(3, 1.1f); + BOOST_CHECK(cb2[0] == 1.1f); + + CB_CONTAINER cb3(5); + cb3.push_back(1); + cb3.push_back(2); + cb3.push_back(3); + cb3.assign((size_t)10, 1); // The size_t cast is not needed. It is present here just because of testing purposes. + BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3[9] == 1); + BOOST_CHECK(cb3.size() == 10); + BOOST_CHECK(cb3.capacity() == 10); +} + +void copy_constructor_and_assign_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + cb1.push_back(5); + CB_CONTAINER cb2 = cb1; + + BOOST_CHECK(cb1 == cb2); + + CB_CONTAINER cb3(20); + cb1.pop_back(); + CB_CONTAINER cb4(3); + cb3 = cb2; + cb3 = cb3; + cb4 = cb1; + + BOOST_CHECK(cb3 == cb2); + BOOST_CHECK(cb4 == cb1); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb2[0] == 2); + BOOST_CHECK(cb3.full()); + BOOST_CHECK(cb3.capacity() == 4); + BOOST_CHECK(cb4.capacity() == 4); + BOOST_CHECK(!cb4.full()); + BOOST_CHECK(*(cb4.end() - 1) == 4); +} + +void swap_test() { + + CB_CONTAINER cb1(2); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + CB_CONTAINER cb2(5); + cb2.push_back(8); + cb2.swap(cb1); + cb2.swap(cb2); + + BOOST_CHECK(cb2.capacity() == 2); + BOOST_CHECK(cb2[0] == 2); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb1.capacity() == 5); + BOOST_CHECK(cb1[0] == 8); + BOOST_CHECK(cb1.size() == 1); +} + +void push_back_test() { + + CB_CONTAINER cb1(5); + cb1.push_back(); + cb1.push_back(A(2)); + BOOST_CHECK(cb1[0].m_n == 1); + BOOST_CHECK(cb1[1].m_n == 2); + + CB_CONTAINER cb2(5); + cb2.push_back(); + BOOST_CHECK(cb2.back() == CB_CONTAINER::value_type()); + + cb2.push_back(1); + BOOST_CHECK(cb2.back() == 1); +} + +void pop_back_test() { + + CB_CONTAINER cb(4); + cb.push_back(1); + cb.push_back(2); + cb.push_back(3); + cb.push_back(4); + cb.push_back(5); + cb.pop_back(); + + BOOST_CHECK(cb.size() == 3); + BOOST_CHECK(!cb.full()); + BOOST_CHECK(cb[0] == 2); +} + +void insert_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + CB_CONTAINER::iterator it1 = cb1.begin() + 1; + it1 = cb1.insert(it1, 10); + CB_CONTAINER cb2(4); + cb2.push_back(1); + cb2.insert(cb2.begin()); + cb2.insert(cb2.begin(), -1); + CB_CONTAINER::iterator it2 = cb2.begin() + 1; + it2 = cb2.insert(it2, 5); + CB_CONTAINER cb3(2); + cb3.insert(cb3.end(), 10); + cb3.insert(cb3.end(), 20); + cb3.insert(cb3.begin(), 30); + cb3.insert(cb3.end(), 40); + + BOOST_CHECK(cb1[1] == 10); + BOOST_CHECK(*it1 == 10); + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb2[1] == 5); + BOOST_CHECK(*it2 == 5); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb3[0] == 20); + BOOST_CHECK(cb3[1] == 40); +} + +void insert_n_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.insert(cb1.begin() + 1, 2, 10); + CB_CONTAINER cb2(2 CB_MIN_CAPACITY, 3); + cb2.insert(cb2.begin(), 10, 5); + CB_CONTAINER cb3(4); + cb3.insert(cb3.end(), 1, 6); + CB_CONTAINER cb4(6); + cb4.push_back(1); + cb4.push_back(2); + cb4.push_back(3); + cb4.push_back(4); + cb4.insert(cb4.begin() + 2, 5, 6); + cb4.insert(cb4.begin() + 2, 0, 7); + + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1[0] == 10); + BOOST_CHECK(cb1[1] == 10); + BOOST_CHECK(cb1[2] == 2); + BOOST_CHECK(cb1[3] == 3); + BOOST_CHECK(cb2[0] == 3); + BOOST_CHECK(cb2[1] == 3); + BOOST_CHECK(cb3[0] == 6); + BOOST_CHECK(cb3.size() == 1); + BOOST_CHECK(cb4.size() == 6); + BOOST_CHECK(cb4[0] == 6); + BOOST_CHECK(cb4[1] == 6); + BOOST_CHECK(cb4[2] == 6); + BOOST_CHECK(cb4[3] == 6); + BOOST_CHECK(cb4[4] == 3); + BOOST_CHECK(cb4[5] == 4); +} + +void insert_range_test() { + + vector v; + v.push_back(11); + v.push_back(12); + v.push_back(13); + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.insert(cb1.begin() + 1, v.begin(), v.end()); + CB_CONTAINER cb2(2 CB_MIN_CAPACITY, 2); + cb2.insert(cb2.end(), v.begin(), v.end()); + CB_CONTAINER cb3(5); + cb3.insert(cb3.end(), v.end(), v.end()); + CB_CONTAINER cb4(5); + cb4.insert(cb4.end(), v.begin(), v.begin() + 1); + Integer array[] = { 5, 6, 7, 8, 9 }; + CB_CONTAINER cb5(6); + cb5.push_back(1); + cb5.push_back(2); + cb5.push_back(3); + cb5.push_back(4); + cb5.insert(cb5.begin() + 2, array, array + 5); + cb5.insert(cb5.begin(), array, array + 5); + + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1[0] == 12); + BOOST_CHECK(cb1[1] == 13); + BOOST_CHECK(cb1[2] == 2); + BOOST_CHECK(cb1[3] == 3); + BOOST_CHECK(cb2[0] == 12); + BOOST_CHECK(cb2[1] == 13); + BOOST_CHECK(cb3.empty()); + BOOST_CHECK(cb4[0] == 11); + BOOST_CHECK(cb4.size() == 1); + BOOST_CHECK(cb5.size() == 6); + BOOST_CHECK(cb5[0] == 6); + BOOST_CHECK(cb5[1] == 7); + BOOST_CHECK(cb5[2] == 8); + BOOST_CHECK(cb5[3] == 9); + BOOST_CHECK(cb5[4] == 3); + BOOST_CHECK(cb5[5] == 4); +} + +void push_front_test() { + + CB_CONTAINER cb1(5); + cb1.push_front(); + cb1.push_front(A(2)); + BOOST_CHECK(cb1[0].m_n == 2); + BOOST_CHECK(cb1[1].m_n == 1); + + CB_CONTAINER cb2(5); + cb2.push_front(); + BOOST_CHECK(cb2.front() == CB_CONTAINER::value_type()); + + cb2.push_front(1); + BOOST_CHECK(cb2.front() == 1); + + CB_CONTAINER cb3(0); + cb3.push_front(10); + BOOST_CHECK(cb3.empty()); +} + +void pop_front_test() { + + CB_CONTAINER cb(4); + cb.push_front(1); + cb.push_front(2); + cb.push_front(3); + cb.push_front(4); + cb.push_front(5); + cb.pop_front(); + + BOOST_CHECK(cb.size() == 3); + BOOST_CHECK(!cb.full()); + BOOST_CHECK(cb[0] == 4); +} + +void rinsert_test() { + + CB_CONTAINER cb1(4); + cb1.push_front(1); + cb1.push_front(2); + cb1.push_front(3); + CB_CONTAINER::iterator it1 = cb1.begin() + 1; + it1 = cb1.rinsert(it1, 10); + CB_CONTAINER cb2(4); + cb2.push_front(1); + cb2.rinsert(cb2.begin()); + cb2.rinsert(cb2.begin(), -1); + CB_CONTAINER::iterator it2 = cb2.end() - 2; + it2 = cb2.rinsert(it2, 5); + CB_CONTAINER cb3(2); + cb3.rinsert(cb3.begin(), 10); + cb3.rinsert(cb3.begin(), 20); + cb3.rinsert(cb3.end(), 30); + cb3.rinsert(cb3.begin(), 40); + CB_CONTAINER cb4(4); + cb4.push_back(1); + cb4.push_back(2); + cb4.push_back(3); + CB_CONTAINER::iterator it3 = cb4.begin() + 1; + it3 = cb4.rinsert(it3, 10); + CB_CONTAINER cb5(4); + cb5.push_back(1); + cb5.rinsert(cb5.begin(), 0); + cb5.rinsert(cb5.begin(), -1); + CB_CONTAINER::iterator it4 = cb5.begin() + 1; + it4 = cb5.rinsert(it4, 5); + CB_CONTAINER cb6(2); + cb6.rinsert(cb6.end(), 10); + cb6.rinsert(cb6.end(), 20); + cb6.rinsert(cb6.begin(), 30); + cb6.rinsert(cb6.end(), 40); + CB_CONTAINER cb7(6); + cb7.push_back(1); + cb7.push_back(2); + cb7.push_back(3); + cb7.push_back(4); + cb7.rinsert(cb7.begin() + 2, 5, 6); + + BOOST_CHECK(cb1[1] == 10); + BOOST_CHECK(*it1 == 10); + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb2[1] == 5); + BOOST_CHECK(*it2 == 5); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb2[3] == 1); + BOOST_CHECK(cb3[0] == 40); + BOOST_CHECK(cb3[1] == 20); + BOOST_CHECK(cb4[1] == 10); + BOOST_CHECK(*it3 == 10); + BOOST_CHECK(cb4.full()); + BOOST_CHECK(cb5[1] == 5); + BOOST_CHECK(*it4 == 5); + BOOST_CHECK(cb5.full()); + BOOST_CHECK(cb6[0] == 30); + BOOST_CHECK(cb6[1] == 10); + BOOST_CHECK(cb7.size() == 6); + BOOST_CHECK(cb7[0] == 1); + BOOST_CHECK(cb7[1] == 2); + BOOST_CHECK(cb7[2] == 6); + BOOST_CHECK(cb7[3] == 6); + BOOST_CHECK(cb7[4] == 6); + BOOST_CHECK(cb7[5] == 6); +} + +void rinsert_n_test() { + + CB_CONTAINER cb1(4); + cb1.push_front(1); + cb1.push_front(2); + cb1.push_front(3); + cb1.rinsert(cb1.begin() + 1, 2, 10); + CB_CONTAINER cb2(2 CB_MIN_CAPACITY, 3); + cb2.rinsert(cb2.begin(), 10, 5); + CB_CONTAINER cb3(4); + cb3.rinsert(cb3.end(), 1, 6); + CB_CONTAINER cb4(4); + cb4.push_back(1); + cb4.push_back(2); + cb4.push_back(3); + cb4.rinsert(cb4.begin() + 1, 2, 10); + Integer array[] = { 5, 6, 7, 8, 9 }; + CB_CONTAINER cb5(6); + cb5.push_back(1); + cb5.push_back(2); + cb5.push_back(3); + cb5.push_back(4); + cb5.rinsert(cb5.begin() + 2, array, array + 5); + cb5.rinsert(cb5.end(), array, array + 5); + + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1[0] == 3); + BOOST_CHECK(cb1[1] == 10); + BOOST_CHECK(cb1[2] == 10); + BOOST_CHECK(cb1[3] == 2); + BOOST_CHECK(cb2[0] == 5); + BOOST_CHECK(cb2[1] == 5); + BOOST_CHECK(cb3[0] == 6); + BOOST_CHECK(cb3.size() == 1); + BOOST_CHECK(cb4.full()); + BOOST_CHECK(cb4[0] == 1); + BOOST_CHECK(cb4[1] == 10); + BOOST_CHECK(cb4[2] == 10); + BOOST_CHECK(cb4[3] == 2); + BOOST_CHECK(cb5.size() == 6); + BOOST_CHECK(cb5[0] == 1); + BOOST_CHECK(cb5[1] == 2); + BOOST_CHECK(cb5[2] == 5); + BOOST_CHECK(cb5[3] == 6); + BOOST_CHECK(cb5[4] == 7); + BOOST_CHECK(cb5[5] == 8); +} + +void rinsert_range_test() { + + vector v; + v.push_back(11); + v.push_back(12); + v.push_back(13); + v.push_back(14); + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.rinsert(cb1.begin() + 1, v.begin(), v.end()); + CB_CONTAINER cb2(2 CB_MIN_CAPACITY, 2); + cb2.rinsert(cb2.begin(), v.begin(), v.end()); + CB_CONTAINER cb3(5); + cb3.rinsert(cb3.begin(), v.end(), v.end()); + CB_CONTAINER cb4(5); + cb4.rinsert(cb4.begin(), v.begin(), v.begin() + 1); + + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1[0] == 1); + BOOST_CHECK(cb1[1] == 11); + BOOST_CHECK(cb1[2] == 12); + BOOST_CHECK(cb1[3] == 13); + BOOST_CHECK(cb2[0] == 11); + BOOST_CHECK(cb2[1] == 12); + BOOST_CHECK(cb3.empty()); + BOOST_CHECK(cb4[0] == 11); + BOOST_CHECK(cb4.size() == 1); +} + +void erase_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + CB_CONTAINER::iterator it1 = cb1.erase(cb1.begin() + 1); + + CB_CONTAINER cb2(1 CB_MIN_CAPACITY, 1); + CB_CONTAINER::iterator it2 = cb2.erase(cb2.begin()); + + BOOST_CHECK(cb1.size() == 2); + BOOST_CHECK(cb1.capacity() == 4); + BOOST_CHECK(*it1 == 3); + BOOST_CHECK(cb2.size() == 0); + BOOST_CHECK(cb2.capacity() == 1); + BOOST_CHECK(it2 == cb2.end()); +} + +void erase_range_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + CB_CONTAINER::iterator it1 = cb1.erase(cb1.begin() + 1, cb1.begin() + 3); + CB_CONTAINER cb2(4); + cb2.push_back(1); + cb2.push_back(2); + cb2.push_back(3); + cb2.push_back(4); + CB_CONTAINER::iterator it2 = cb2.erase(cb2.begin(), cb2.begin()); + + BOOST_CHECK(cb1.size() == 2); + BOOST_CHECK(cb1.capacity() == 4); + BOOST_CHECK(*it1 == 4); + BOOST_CHECK(cb2.size() == 4); + BOOST_CHECK(cb2[0] == 1); + BOOST_CHECK(cb2[3] == 4); + BOOST_CHECK(*it2 == 1); +} + +void clear_test() { + + CB_CONTAINER cb(4); + cb.push_back(1); + cb.push_back(2); + cb.push_back(3); + cb.push_back(4); + cb.clear(); + + BOOST_CHECK(cb.empty()); +} + +void equality_test() { + + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + CB_CONTAINER cb2(10); + cb2.push_back(1); + cb2.push_back(2); + cb2.push_back(3); + cb2.push_back(4); + + BOOST_CHECK(cb1 == cb2); + BOOST_CHECK(!(cb2 != cb1)); +} + +void lexicographical_comparison_test() { + + CB_CONTAINER cb1(10); + cb1.push_back('a'); + cb1.push_back('d'); + cb1.push_back('a'); + cb1.push_back('m'); + CB_CONTAINER cb2(5); + cb2.push_back('j'); + cb2.push_back('o'); + cb2.push_back('h'); + cb2.push_back('n'); + + BOOST_CHECK(cb2 > cb1); + BOOST_CHECK(cb1 < cb2); +} + +void assign_range_test() { + + vector v; + v.push_back(11); + v.push_back(12); + v.push_back(13); + CB_CONTAINER cb1(4); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.assign(v.begin() + 1, v.end()); + CB_CONTAINER cb2(2); + cb2.push_back(1); + cb2.push_back(2); + cb2.assign(v.begin(), v.end()); + + BOOST_CHECK(!cb1.full()); + BOOST_CHECK(cb1[0] == 12); + BOOST_CHECK(cb1[1] == 13); + BOOST_CHECK(cb2.full()); + BOOST_CHECK(cb2.capacity() == 3); + BOOST_CHECK(cb2[0] == 11); + BOOST_CHECK(cb2[1] == 12); + BOOST_CHECK(cb2[2] == 13); + BOOST_CHECK(cb2.size() == (size_t)distance(v.begin(), v.end())); +} + +// test of the example (introduced in the documentation) +void example_test() { + + CB_CONTAINER cb1(3); + cb1.push_back(1); + cb1.push_back(2); + cb1.push_back(3); + cb1.push_back(4); + int sum = accumulate(cb1.begin(), cb1.end(), 0); + + BOOST_CHECK(cb1[0] == 2); + BOOST_CHECK(cb1[1] == 3); + BOOST_CHECK(cb1[2] == 4); + BOOST_CHECK(sum == 9); + BOOST_CHECK(cb1.full()); + BOOST_CHECK(cb1.size() == 3); + BOOST_CHECK(cb1.capacity() == 3); + + CB_CONTAINER cb2(5 CB_MIN_CAPACITY, 1); + cb2.insert(cb2.begin(), 2); + + BOOST_CHECK(cb2[0] == 1); + BOOST_CHECK(cb2[1] == 1); + BOOST_CHECK(cb2[2] == 1); + BOOST_CHECK(cb2[3] == 1); + BOOST_CHECK(cb2[4] == 1); + + vector v; + v.push_back(100); + v.push_back(200); + v.push_back(300); + cb2.insert(cb2.begin() + 1, v.begin(), v.end()); + + BOOST_CHECK(cb2[0] == 300); + BOOST_CHECK(cb2[1] == 1); + BOOST_CHECK(cb2[2] == 1); + BOOST_CHECK(cb2[3] == 1); + BOOST_CHECK(cb2[4] == 1); + + CB_CONTAINER cb3(3); + cb3.push_back(1); + cb3.push_back(2); + cb3.push_back(3); + cb3.push_back(4); + cb3.push_back(5); + BOOST_CHECK(cb3[0] == 3); + BOOST_CHECK(cb3[1] == 4); + BOOST_CHECK(cb3[2] == 5); + + cb3.pop_back(); + cb3.pop_front(); + BOOST_CHECK(cb3[0] == 4); +} + +void element_destruction_test() { + + CB_CONTAINER cb(5); + cb.push_back(B()); + cb.push_back(B()); + cb.push_back(B()); + int prevCount = B::count(); + cb.clear(); + + BOOST_CHECK(cb.empty()); + BOOST_CHECK(prevCount == 3); + BOOST_CHECK(B::count() == 0); +} + +void const_methods_test() { + + vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + v.push_back(4); + v.push_back(5); + const CB_CONTAINER cb(5 CB_MIN_CAPACITY, v.begin(), v.end()); + + BOOST_CHECK(*cb.begin() == 1); + BOOST_CHECK(*(cb.end() - 1) == 5); + BOOST_CHECK(*cb.rbegin() == 5); + BOOST_CHECK(*(cb.rend() - 1) == 1); + BOOST_CHECK(cb[0] == 1); + BOOST_CHECK(cb.at(1) == 2); + BOOST_CHECK(cb.front() == 1); + BOOST_CHECK(cb.back() == 5); +} + +void adaptor_test() { + int array[] = {0, 1, 2, 3}; + Adaptor container(5); + container.insert(container.begin(), array, array + 4); + + BOOST_CHECK(container.size() == 4); + BOOST_CHECK(container[0] == 0); + BOOST_CHECK(container[1] == 1); + BOOST_CHECK(container[2] == 2); + BOOST_CHECK(container[3] == 3); + + container.insert(container.begin() + 1, array, array + 4); + + BOOST_CHECK(container.size() == 8); + BOOST_CHECK(container[0] == 0); + BOOST_CHECK(container[1] == 0); + BOOST_CHECK(container[2] == 1); + BOOST_CHECK(container[3] == 2); + BOOST_CHECK(container[4] == 3); + BOOST_CHECK(container[5] == 1); + BOOST_CHECK(container[6] == 2); + BOOST_CHECK(container[7] == 3); +} + +int Integer::ms_exception_trigger = 0; +int B::ms_count = 0; + +// add common tests into a test suite +void add_common_tests(test_suite* tests) { + tests->add(BOOST_TEST_CASE(&basic_test)); + tests->add(BOOST_TEST_CASE(&constructor_and_element_access_test)); + tests->add(BOOST_TEST_CASE(&size_test)); + tests->add(BOOST_TEST_CASE(&boundary_capacity_test)); + tests->add(BOOST_TEST_CASE(&begin_and_end_test)); + tests->add(BOOST_TEST_CASE(&rbegin_and_rend_test)); + tests->add(BOOST_TEST_CASE(&element_access_and_insert_test)); + tests->add(BOOST_TEST_CASE(&at_test)); + tests->add(BOOST_TEST_CASE(&front_and_back_test)); + tests->add(BOOST_TEST_CASE(&data_test)); + tests->add(BOOST_TEST_CASE(&capacity_test)); + tests->add(BOOST_TEST_CASE(&full_and_empty_test)); + tests->add(BOOST_TEST_CASE(&set_capacity_test)); + tests->add(BOOST_TEST_CASE(&resize_test)); + tests->add(BOOST_TEST_CASE(&constructor_test)); + tests->add(BOOST_TEST_CASE(&assign_test)); + tests->add(BOOST_TEST_CASE(©_constructor_and_assign_test)); + tests->add(BOOST_TEST_CASE(&swap_test)); + tests->add(BOOST_TEST_CASE(&push_back_test)); + tests->add(BOOST_TEST_CASE(&pop_back_test)); + tests->add(BOOST_TEST_CASE(&insert_test)); + tests->add(BOOST_TEST_CASE(&insert_n_test)); + tests->add(BOOST_TEST_CASE(&insert_range_test)); + tests->add(BOOST_TEST_CASE(&push_front_test)); + tests->add(BOOST_TEST_CASE(&pop_front_test)); + tests->add(BOOST_TEST_CASE(&rinsert_test)); + tests->add(BOOST_TEST_CASE(&rinsert_n_test)); + tests->add(BOOST_TEST_CASE(&rinsert_range_test)); + tests->add(BOOST_TEST_CASE(&erase_test)); + tests->add(BOOST_TEST_CASE(&erase_range_test)); + tests->add(BOOST_TEST_CASE(&clear_test)); + tests->add(BOOST_TEST_CASE(&equality_test)); + tests->add(BOOST_TEST_CASE(&lexicographical_comparison_test)); + tests->add(BOOST_TEST_CASE(&assign_range_test)); + tests->add(BOOST_TEST_CASE(&example_test)); + tests->add(BOOST_TEST_CASE(&element_destruction_test)); + tests->add(BOOST_TEST_CASE(&const_methods_test)); + tests->add(BOOST_TEST_CASE(&adaptor_test)); +} diff --git a/test/test.hpp b/test/test.hpp new file mode 100644 index 0000000..09a3748 --- /dev/null +++ b/test/test.hpp @@ -0,0 +1,115 @@ +// Header file for the test of the circular buffer library. + +// Copyright (c) 2003-2004 Jan Gaspar + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_CIRCULAR_BUFFER_TEST_HPP) +#define BOOST_CIRCULAR_BUFFER_TEST_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include "../../../boost/circular_buffer.hpp" +#include +#include +#include +#if !defined(BOOST_NO_EXCEPTIONS) + #include +#endif + +// Integer - substitute for int - more appropriate for testing +class Integer { +private: + int* m_pValue; + static int ms_exception_trigger; + void check_exception() { + if (ms_exception_trigger > 0) { + if (--ms_exception_trigger == 0) { + delete m_pValue; + m_pValue = 0; +#if !defined(BOOST_NO_EXCEPTIONS) + throw std::exception(); +#endif + } + } + } +public: + Integer() : m_pValue(new int(0)) { check_exception(); } + Integer(int i) : m_pValue(new int(i)) { check_exception(); } + Integer(const Integer& src) : m_pValue(new int(src)) { check_exception(); } + ~Integer() { delete m_pValue; } + operator int () const { return *m_pValue; } + static void set_exception_trigger(int n) { ms_exception_trigger = n; } +private: + Integer& operator = (const Integer& src); // disabled +}; + +struct A +{ + A() : m_n(1) {} + A(int n) : m_n(n) {} + int m_n; +private: + A& operator = (const A& src); // disabled +}; + +class B { +public: + B() { increment(); } + B(const B& y) { y.increment(); } + ~B() { decrement(); } + static int count() { return ms_count; } +private: + void increment() const { ++ms_count; } + void decrement() const { --ms_count; } + static int ms_count; + B& operator = (const B& src); // disabled +}; + +class C { +public: + C() : m_num(255) {} + virtual int test_reference1() const { return m_num; } + int test_reference2() const { return 255; } +private: + int m_num; + C& operator = (const C& src); // disabled +}; + +template class Adaptor { +private: + boost::circular_buffer m_buff; +public: + typedef typename boost::circular_buffer::iterator iterator; + typedef typename boost::circular_buffer::size_type size_type; + + Adaptor(size_type capacity) : m_buff(capacity) {} + template + Adaptor(size_type capacity, InputIterator first, InputIterator last) + : m_buff(capacity, first, last) {} + + iterator begin() { return m_buff.begin(); } + iterator end() { return m_buff.end(); } + size_type size() const { return m_buff.size(); } + size_type capacity() const { return m_buff.capacity(); } + T& operator [] (size_type index) { return m_buff[index]; } + + template + void insert(iterator pos, InputIterator first, InputIterator last) { + size_type new_size = size() + distance(first, last); + if (new_size > capacity()) { + boost::circular_buffer buff(new_size, begin(), pos); + buff.insert(buff.end(), first, last); + buff.insert(buff.end(), pos, end()); + m_buff.swap(buff); + } else { + m_buff.insert(pos, first, last); + } + } +}; + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_TEST_HPP)