shared_vector: simplify slice()

Correctly tracks capacity when user
over-slices.
This commit is contained in:
Michael Davidsaver
2013-08-06 11:32:34 -04:00
parent 31be738c10
commit de70d90603
2 changed files with 33 additions and 15 deletions

View File

@@ -47,13 +47,18 @@ namespace detail {
template<typename E1> friend class shared_vector_base;
protected:
std::tr1::shared_ptr<E> m_data;
//! Offset in the data array of first element
//! Offset in the data array of first visible element
size_t m_offset;
//! Number of visible elements between m_offset and end of data
size_t m_count;
//! Total number of elements between m_offset and the end of data
size_t m_total;
/* invariants
* m_count <= m_total (enforced)
* m_offset + m_total <= (size_t)-1 (checked w/ assert())
*/
public:
//! @brief Empty vector (not very interesting)
@@ -68,6 +73,9 @@ namespace detail {
{
if(!m_data.get()) {
m_offset = m_total = m_count = 0;
} else {
// ensure we won't have integer overflows later
assert( m_offset <= ((size_t)-1) - m_total);
}
}
public:
@@ -96,6 +104,8 @@ namespace detail {
protected:
typedef typename meta::strip_const<E>::type _E_non_const;
public:
//! Constructor used to implement freeze().
//! Should not be called directly.
shared_vector_base(shared_vector_base<_E_non_const>& O,
_shared_vector_freeze_tag)
:m_data()
@@ -109,6 +119,8 @@ namespace detail {
O.clear();
}
//! Constructor used to implement thaw().
//! Should not be called directly.
shared_vector_base(shared_vector<const E>& O,
_shared_vector_thaw_tag)
:m_data()
@@ -180,20 +192,16 @@ namespace detail {
*/
void slice(size_t offset, size_t length=(size_t)-1)
{
if(offset>m_total)
offset = m_total;
if(offset>m_count)
offset = m_count; // will slice down to zero length
const size_t max_count = m_count - offset;
m_offset += offset;
m_total -= offset;
if(offset>m_count) {
m_count = 0;
} else {
if(length > m_count - offset)
length = m_count - offset;
m_count = length;
}
m_count = std::min(length, max_count);
}
// Access to members.

View File

@@ -250,7 +250,13 @@ static void testSlice()
testOk1(half2.dataOffset()==5);
testOk1(half2a.dataOffset()==5);
testOk1(half2.size() == half2a.size());
testOk1(half1.size()==5);
testOk1(half2.size()==5);
testOk1(half2a.size()==5);
testOk1(half1.dataTotal()==10);
testOk1(half2.dataTotal()==5);
testOk1(half2a.dataTotal()==5);
testOk1(original.data() == half1.data());
testOk1(half2.data() == half2a.data());
@@ -259,13 +265,17 @@ static void testSlice()
half2.slice(1);
half2a.slice(1,1);
testOk1(half1.dataOffset()==5);
testOk1(half2.dataOffset()==6);
testOk1(half2a.dataOffset()==6);
testOk1(half1.size()==0);
testOk1(half2.size()==4);
testOk1(half2a.size()==1);
testOk1(half1.dataOffset()==10);
testOk1(half2.dataOffset()==6);
testOk1(half2a.dataOffset()==6);
testOk1(half1.dataTotal()==5);
testOk1(half2.dataTotal()==4);
testOk1(half2a.dataTotal()==4);
half2.clear();
testOk1(half2.dataOffset()==0);
@@ -525,7 +535,7 @@ static void testICE()
MAIN(testSharedVector)
{
testPlan(154);
testPlan(162);
testDiag("Tests for shared_vector");
testDiag("sizeof(shared_vector<int>)=%lu",