shared_vector: simplify slice()
Correctly tracks capacity when user over-slices.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user