mirror of https://github.com/davisking/dlib.git
Added a circular_buffer object. It is like sliding_buffer except it can
have sizes which aren't powers of 2.
This commit is contained in:
parent
90c897f6f0
commit
cd10054144
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "sliding_buffer/sliding_buffer_kernel_1.h"
|
||||
#include "sliding_buffer/sliding_buffer_kernel_c.h"
|
||||
#include "sliding_buffer/circular_buffer.h"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_CIRCULAR_BuFFER_H__
|
||||
#define DLIB_CIRCULAR_BuFFER_H__
|
||||
|
||||
#include "circular_buffer_abstract.h"
|
||||
#include <vector>
|
||||
#include "../algs.h"
|
||||
#include "../serialize.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class circular_buffer
|
||||
{
|
||||
public:
|
||||
typedef default_memory_manager mem_manager_type;
|
||||
typedef T value_type;
|
||||
typedef T type;
|
||||
|
||||
circular_buffer()
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
void clear (
|
||||
)
|
||||
{
|
||||
offset = 0;
|
||||
data.clear();
|
||||
}
|
||||
|
||||
T& operator[] ( unsigned long i)
|
||||
{
|
||||
DLIB_ASSERT(i < size(),
|
||||
"\t T& circular_buffer::operator[](i)"
|
||||
<< "\n\t You have supplied an invalid index"
|
||||
<< "\n\t this: " << this
|
||||
<< "\n\t i: " << i
|
||||
<< "\n\t size(): " << size()
|
||||
);
|
||||
return data[(i+offset)%data.size()];
|
||||
}
|
||||
|
||||
const T& operator[] ( unsigned long i) const
|
||||
{
|
||||
DLIB_ASSERT(i < size(),
|
||||
"\t const T& circular_buffer::operator[](i)"
|
||||
<< "\n\t You have supplied an invalid index"
|
||||
<< "\n\t this: " << this
|
||||
<< "\n\t i: " << i
|
||||
<< "\n\t size(): " << size()
|
||||
);
|
||||
return data[(i+offset)%data.size()];
|
||||
}
|
||||
|
||||
void resize(unsigned long size, const T& value = T()) { data.resize(size,value); }
|
||||
void assign(unsigned long size, const T& value) { data.assign(size,value); }
|
||||
|
||||
unsigned long size() const { return data.size(); }
|
||||
|
||||
void push_front(const T& value)
|
||||
{
|
||||
if (data.size() != 0)
|
||||
{
|
||||
offset = (offset - 1 + data.size())%data.size();
|
||||
data[offset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(const T& value)
|
||||
{
|
||||
if (data.size() != 0)
|
||||
{
|
||||
data[offset] = value;
|
||||
offset = (offset + 1 + data.size())%data.size();
|
||||
}
|
||||
}
|
||||
|
||||
T& front(
|
||||
)
|
||||
{
|
||||
DLIB_CASSERT(size() > 0,
|
||||
"\t T& circular_buffer::front()"
|
||||
<< "\n\t You can't call front() on an empty circular_buffer"
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
const T& front(
|
||||
) const
|
||||
{
|
||||
DLIB_CASSERT(size() > 0,
|
||||
"\t const T& circular_buffer::front()"
|
||||
<< "\n\t You can't call front() on an empty circular_buffer"
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
T& back(
|
||||
)
|
||||
{
|
||||
DLIB_CASSERT(size() > 0,
|
||||
"\t T& circular_buffer::back()"
|
||||
<< "\n\t You can't call back() on an empty circular_buffer"
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
return (*this)[size()-1];
|
||||
}
|
||||
|
||||
const T& back(
|
||||
) const
|
||||
{
|
||||
DLIB_CASSERT(size() > 0,
|
||||
"\t const T& circular_buffer::back()"
|
||||
<< "\n\t You can't call back() on an empty circular_buffer"
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
return (*this)[size()-1];
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> data;
|
||||
|
||||
unsigned long offset;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void swap (
|
||||
circular_buffer<T>& a,
|
||||
circular_buffer<T>& b
|
||||
) { a.swap(b); }
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void serialize (
|
||||
const circular_buffer<T>& item,
|
||||
std::ostream& out
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
serialize(item.size(),out);
|
||||
for (unsigned long i = 0; i < item.size(); ++i)
|
||||
serialize(item[i],out);
|
||||
}
|
||||
catch (serialization_error& e)
|
||||
{
|
||||
throw serialization_error(e.info + "\n while serializing object of type circular_buffer");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void deserialize (
|
||||
circular_buffer<T>& item,
|
||||
std::istream& in
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
unsigned long size;
|
||||
deserialize(size,in);
|
||||
item.resize(size);
|
||||
for (unsigned long i = 0; i < size; ++i)
|
||||
deserialize(item[i],in);
|
||||
}
|
||||
catch (serialization_error& e)
|
||||
{
|
||||
item.clear();
|
||||
throw serialization_error(e.info + "\n while deserializing object of type circular_buffer");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_CIRCULAR_BuFFER_H__
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#undef DLIB_CIRCULAR_BuFFER_ABSTRACT_H__
|
||||
#ifdef DLIB_CIRCULAR_BuFFER_ABSTRACT_H__
|
||||
|
||||
#include "../algs.h"
|
||||
#include "../serialize.h"
|
||||
|
||||
namespace dlib
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
class circular_buffer
|
||||
{
|
||||
/*!
|
||||
REQUIREMENTS ON T
|
||||
T must have a default constructor and be copyable.
|
||||
|
||||
POINTERS AND REFERENCES TO INTERNAL DATA
|
||||
swap(), size(), front(), back(), and operator[] functions do
|
||||
not invalidate pointers or references to internal data.
|
||||
All other functions have no such guarantee.
|
||||
|
||||
INITIAL VALUE
|
||||
- size() == 0
|
||||
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This object is a circular buffer. This means that when objects
|
||||
are pushed onto one of its ends it does not grow in size. Instead,
|
||||
it shifts all elements over one to make room for the new element
|
||||
and the element at the opposing end falls off the buffer and is
|
||||
lost.
|
||||
!*/
|
||||
|
||||
public:
|
||||
typedef default_memory_manager mem_manager_type;
|
||||
typedef T value_type;
|
||||
typedef T type;
|
||||
|
||||
circular_buffer(
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #size() == 0
|
||||
- this object is properly initialized
|
||||
!*/
|
||||
|
||||
void clear (
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- this object has its initial value
|
||||
- #size() == 0
|
||||
!*/
|
||||
|
||||
T& operator[] (
|
||||
unsigned long i
|
||||
) const;
|
||||
/*!
|
||||
requires
|
||||
- i < size()
|
||||
ensures
|
||||
- returns a non-const reference to the i-th element of this circular buffer
|
||||
!*/
|
||||
|
||||
const T& operator[] (
|
||||
unsigned long i
|
||||
) const;
|
||||
/*!
|
||||
requires
|
||||
- i < size()
|
||||
ensures
|
||||
- returns a const reference to the i-th element of this circular buffer
|
||||
!*/
|
||||
|
||||
void resize(
|
||||
unsigned long new_size,
|
||||
const T& c = T()
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #size() == new_size
|
||||
- any element with index between 0 and new_size - 1 which was in the
|
||||
circular_buffer before the call to resize() retains its value and index.
|
||||
All other elements have a value given by c.
|
||||
!*/
|
||||
|
||||
unsigned long size(
|
||||
) const;
|
||||
/*!
|
||||
ensures
|
||||
- returns the number of elements in this circular buffer
|
||||
!*/
|
||||
|
||||
T& front(
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- size() > 0
|
||||
ensures
|
||||
- returns a reference to (*this)[0]
|
||||
!*/
|
||||
|
||||
const T& front(
|
||||
) const;
|
||||
/*!
|
||||
requires
|
||||
- size() > 0
|
||||
ensures
|
||||
- returns a const reference to (*this)[0]
|
||||
!*/
|
||||
|
||||
T& back(
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- size() > 0
|
||||
ensures
|
||||
- returns a reference to (*this)[size()-1]
|
||||
!*/
|
||||
|
||||
const T& back(
|
||||
) const;
|
||||
/*!
|
||||
requires
|
||||
- size() > 0
|
||||
ensures
|
||||
- returns a const reference to (*this)[size()-1]
|
||||
!*/
|
||||
|
||||
void push_front(
|
||||
const T& value
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #size() == size()
|
||||
(i.e. the size of this object does not change)
|
||||
- if (size() != 0) then
|
||||
- #front() == value
|
||||
- all items are shifted over such that,
|
||||
- #(*this)[1] == (*this)[0]
|
||||
- #(*this)[2] == (*this)[1]
|
||||
- #(*this)[3] == (*this)[2]
|
||||
- etc.
|
||||
- back() is shifted out of the circular buffer
|
||||
- else
|
||||
- This function has no effect on this object
|
||||
!*/
|
||||
|
||||
void push_back(
|
||||
const T& value
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- #size() == size()
|
||||
(i.e. the size of this object does not change)
|
||||
- if (size() != 0) then
|
||||
- #back() == value
|
||||
- all items are shifted over such that,
|
||||
- front() is shifted out of the circular buffer
|
||||
- #(*this)[0] == (*this)[1]
|
||||
- #(*this)[1] == (*this)[2]
|
||||
- #(*this)[2] == (*this)[3]
|
||||
- etc.
|
||||
- else
|
||||
- This function has no effect on this object
|
||||
!*/
|
||||
|
||||
void swap (
|
||||
circular_buffer& item
|
||||
);
|
||||
/*!
|
||||
ensures
|
||||
- swaps *this with item
|
||||
!*/
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void swap (
|
||||
circular_buffer<T>& a,
|
||||
circular_buffer<T>& b
|
||||
) { a.swap(b); }
|
||||
/*!
|
||||
provides a global swap function
|
||||
!*/
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void serialize (
|
||||
const circular_buffer<T>& item,
|
||||
std::ostream& out
|
||||
);
|
||||
/*!
|
||||
provides serialization support
|
||||
!*/
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
void deserialize (
|
||||
circular_buffer<T>& item,
|
||||
std::istream& in
|
||||
);
|
||||
/*!
|
||||
provides deserialization support
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_CIRCULAR_BuFFER_ABSTRACT_H__
|
||||
|
||||
|
Loading…
Reference in New Issue