mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-20 05:54:54 -04:00
716 lines
22 KiB
C++
716 lines
22 KiB
C++
// Filename: sparseArray.cxx
|
|
// Created by: drose (14Feb07)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "sparseArray.h"
|
|
#include "bitArray.h"
|
|
|
|
TypeHandle SparseArray::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::Constructor (from BitArray)
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
SparseArray::
|
|
SparseArray(const BitArray &from) {
|
|
bool empty_bit = from.get_highest_bits();
|
|
_inverse = empty_bit;
|
|
|
|
int begin = 0;
|
|
bool current_state = from.get_bit(0);
|
|
int i = 0;
|
|
|
|
// By including get_num_bits()--one more than the last bit--in this
|
|
// traversal, we guarantee that we will end on the empty_bit state
|
|
// (because the last bit we visit will be one of the highest_bits).
|
|
while (i <= from.get_num_bits()) {
|
|
if (from.get_bit(i) != current_state) {
|
|
// End of a run.
|
|
if (current_state != empty_bit) {
|
|
Subrange range(begin, i);
|
|
_subranges.push_back(range);
|
|
}
|
|
begin = i;
|
|
current_state = !current_state;
|
|
}
|
|
++i;
|
|
}
|
|
|
|
nassertv(current_state == empty_bit);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_num_on_bits
|
|
// Access: Published
|
|
// Description: Returns the number of bits that are set to 1 in the
|
|
// array. Returns -1 if there are an infinite number of
|
|
// 1 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_num_on_bits() const {
|
|
if (_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
int result = 0;
|
|
Subranges::const_iterator si;
|
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
|
result += (*si)._end - (*si)._begin;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_num_off_bits
|
|
// Access: Published
|
|
// Description: Returns the number of bits that are set to 0 in the
|
|
// array. Returns -1 if there are an infinite number of
|
|
// 0 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_num_off_bits() const {
|
|
if (!_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
int result = 0;
|
|
Subranges::const_iterator si;
|
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
|
result += (*si)._end - (*si)._begin;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_lowest_on_bit
|
|
// Access: Published
|
|
// Description: Returns the index of the lowest 1 bit in the array.
|
|
// Returns -1 if there are no 1 bits or if there are an
|
|
// infinite number of 1 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_lowest_on_bit() const {
|
|
if (_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
if (_subranges.empty()) {
|
|
return -1;
|
|
}
|
|
|
|
return _subranges[0]._begin;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_lowest_off_bit
|
|
// Access: Published
|
|
// Description: Returns the index of the lowest 0 bit in the array.
|
|
// Returns -1 if there are no 0 bits or if there are an
|
|
// infinite number of 1 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_lowest_off_bit() const {
|
|
if (!_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
if (_subranges.empty()) {
|
|
return -1;
|
|
}
|
|
|
|
return _subranges[0]._begin;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_highest_on_bit
|
|
// Access: Published
|
|
// Description: Returns the index of the highest 1 bit in the array.
|
|
// Returns -1 if there are no 1 bits or if there an
|
|
// infinite number of 1 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_highest_on_bit() const {
|
|
if (_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
if (_subranges.empty()) {
|
|
return -1;
|
|
}
|
|
|
|
return _subranges[_subranges.size() - 1]._end - 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_highest_off_bit
|
|
// Access: Published
|
|
// Description: Returns the index of the highest 0 bit in the array.
|
|
// Returns -1 if there are no 0 bits or if there an
|
|
// infinite number of 1 bits.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_highest_off_bit() const {
|
|
if (!_inverse) {
|
|
return -1;
|
|
}
|
|
|
|
if (_subranges.empty()) {
|
|
return -1;
|
|
}
|
|
|
|
return _subranges[_subranges.size() - 1]._end - 1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::get_next_higher_different_bit
|
|
// Access: Published
|
|
// Description: Returns the index of the next bit in the array, above
|
|
// low_bit, whose value is different that the value of
|
|
// low_bit. Returns low_bit again if all bits higher
|
|
// than low_bit have the same value.
|
|
//
|
|
// This can be used to quickly iterate through all of
|
|
// the bits in the array.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
get_next_higher_different_bit(int low_bit) const {
|
|
Subrange range(low_bit, low_bit + 1);
|
|
Subranges::const_iterator si = _subranges.lower_bound(range);
|
|
if (si == _subranges.end()) {
|
|
// That was the end of the array.
|
|
return low_bit;
|
|
}
|
|
|
|
if (low_bit >= (*si)._begin) {
|
|
return (*si)._end;
|
|
}
|
|
|
|
int next = (*si)._begin;
|
|
|
|
if (si != _subranges.begin()) {
|
|
--si;
|
|
if (low_bit < (*si)._end) {
|
|
return (*si)._end;
|
|
}
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::has_bits_in_common
|
|
// Access: Published
|
|
// Description: Returns true if this SparseArray has any "one" bits in
|
|
// common with the other one, false otherwise.
|
|
//
|
|
// This is equivalent to (array & other) != 0, but may
|
|
// be faster.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool SparseArray::
|
|
has_bits_in_common(const SparseArray &other) const {
|
|
if (_inverse && other._inverse) {
|
|
// Yup, in fact we have an infinite number of bits in common.
|
|
return true;
|
|
}
|
|
|
|
if (_inverse != other._inverse) {
|
|
// We'll handle this tricky case the lazy way.
|
|
return !(*this & other).is_zero();
|
|
}
|
|
|
|
// Actually, we'll handle this easy case the lazy way too. Maybe
|
|
// later we'll do this smarter.
|
|
return !(*this & other).is_zero();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::output
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
output(ostream &out) const {
|
|
out << "[ ";
|
|
if (_inverse) {
|
|
out << "all except: ";
|
|
}
|
|
Subranges::const_iterator si;
|
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
|
if ((*si)._end == (*si)._begin + 1) {
|
|
// A single element.
|
|
out << (*si)._begin << ", ";
|
|
} else {
|
|
// A range of elements.
|
|
out << (*si)._begin << "-" << ((*si)._end - 1) << ", ";
|
|
}
|
|
}
|
|
out << "]";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::compare_to
|
|
// Access: Published
|
|
// Description: Returns a number less than zero if this SparseArray
|
|
// sorts before the indicated other SparseArray, greater
|
|
// than zero if it sorts after, or 0 if they are
|
|
// equivalent. This is based on the same ordering
|
|
// defined by operator <.
|
|
////////////////////////////////////////////////////////////////////
|
|
int SparseArray::
|
|
compare_to(const SparseArray &other) const {
|
|
if (_inverse != other._inverse) {
|
|
return _inverse ? 1 : -1;
|
|
}
|
|
|
|
Subranges::const_reverse_iterator ai = _subranges.rbegin();
|
|
Subranges::const_reverse_iterator bi = other._subranges.rbegin();
|
|
|
|
while (ai != _subranges.rend() && bi != other._subranges.rend()) {
|
|
if ((*ai)._end < (*bi)._end) {
|
|
// B is higher.
|
|
return -1;
|
|
} else if ((*bi)._end < (*ai)._end) {
|
|
// A is higher.
|
|
return 1;
|
|
} else if ((*ai)._begin < (*bi)._begin) {
|
|
// A is higher.
|
|
return 1;
|
|
} else if ((*bi)._begin < (*ai)._begin) {
|
|
// B is higher.
|
|
return -1;
|
|
}
|
|
|
|
--ai;
|
|
--bi;
|
|
}
|
|
|
|
if (ai != _subranges.rend()) {
|
|
// A is higher.
|
|
return 1;
|
|
}
|
|
if (bi != other._subranges.rend()) {
|
|
// B is higher.
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::operator &=
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
operator &= (const SparseArray &other) {
|
|
// We do this the slow and stupid way. This could be done much
|
|
// better with a little effort, but I'm not at all sure it's worth
|
|
// the effort. If you need fast boolean operations, you should
|
|
// probably be using a BitArray.
|
|
|
|
if (_inverse && other._inverse) {
|
|
do_union(other);
|
|
|
|
} else if (!_inverse && !other._inverse) {
|
|
do_intersection(other);
|
|
|
|
} else if (_inverse && !other._inverse) {
|
|
// a & b == b & a
|
|
(*this) = other & (*this);
|
|
|
|
} else if (!_inverse && other._inverse) {
|
|
do_intersection_neg(other);
|
|
|
|
} else {
|
|
// TODO.
|
|
nassertv(false);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::operator |=
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
operator |= (const SparseArray &other) {
|
|
// We do this the slow and stupid way. This could be done much
|
|
// better with a little effort, but I'm not at all sure it's worth
|
|
// the effort. If you need fast boolean operations, you should
|
|
// probably be using a BitArray.
|
|
|
|
if (_inverse && other._inverse) {
|
|
do_intersection(other);
|
|
|
|
} else if (!_inverse && !other._inverse) {
|
|
do_union(other);
|
|
|
|
} else if (_inverse && !other._inverse) {
|
|
do_intersection_neg(other);
|
|
|
|
} else if (!_inverse && other._inverse) {
|
|
// a | b == b | a
|
|
(*this) = other | (*this);
|
|
|
|
} else {
|
|
nassertv(false);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::operator ^=
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
operator ^= (const SparseArray &other) {
|
|
// We do this the slow and stupid way. This could be done much
|
|
// better with a little effort, but I'm not at all sure it's worth
|
|
// the effort. If you need fast boolean operations, you should
|
|
// probably be using a BitArray.
|
|
|
|
(*this) = ((*this) | other) & ~((*this) & other);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_add_range
|
|
// Access: Private
|
|
// Description: Adds the consecutive range of integers beginning at
|
|
// begin, but not including end, to the array. If this
|
|
// range overlaps with another range already in the
|
|
// array, the result is the union.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_add_range(int begin, int end) {
|
|
if (begin >= end) {
|
|
// Empty range.
|
|
return;
|
|
}
|
|
|
|
Subrange range(begin, end);
|
|
Subranges::iterator si = _subranges.lower_bound(range);
|
|
if (si == _subranges.end()) {
|
|
if (!_subranges.empty()) {
|
|
si = _subranges.begin() + _subranges.size() - 1;
|
|
if ((*si)._end >= begin) {
|
|
// The new range expands the last element of the array to the right.
|
|
(*si)._end = end;
|
|
// It might also expand it to the left; fall through.
|
|
} else {
|
|
// The new range is completely after the last element of the array.
|
|
_subranges.push_back(range);
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
// The new range is completely after the last element of the array.
|
|
_subranges.push_back(range);
|
|
return;
|
|
}
|
|
}
|
|
|
|
nassertv((*si)._end >= end);
|
|
|
|
if ((*si)._begin > end) {
|
|
if (si != _subranges.begin()) {
|
|
Subranges::iterator si2 = si;
|
|
--si2;
|
|
if ((*si2)._end >= begin) {
|
|
// The new range expands an element within the array to the
|
|
// right (but does not intersect the next element).
|
|
(*si2)._end = end;
|
|
// It might also expand it to the left; fall through.
|
|
si = si2;
|
|
} else {
|
|
// The new range does not intersect any elements in the array.
|
|
_subranges.insert_unverified(si, range);
|
|
return;
|
|
}
|
|
} else {
|
|
// The new range does not intersect any elements in the array.
|
|
_subranges.insert_unverified(si, range);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check if the new range overlaps with any elements to the left.
|
|
while (si != _subranges.begin()) {
|
|
Subranges::iterator si2 = si;
|
|
--si2;
|
|
if ((*si2)._end >= begin) {
|
|
// The new range straddles two elements, so they get combined.
|
|
(*si2)._end = (*si)._end;
|
|
_subranges.erase(si);
|
|
} else {
|
|
// Stop here.
|
|
break;
|
|
}
|
|
si = si2;
|
|
}
|
|
|
|
if ((*si)._begin > begin) {
|
|
// The new range expands an element to the left.
|
|
(*si)._begin = begin;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_remove_range
|
|
// Access: Private
|
|
// Description: Removes the consecutive range of integers beginning
|
|
// at begin, but not including end, from the array.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_remove_range(int begin, int end) {
|
|
if (begin >= end) {
|
|
// Empty range.
|
|
return;
|
|
}
|
|
|
|
Subrange range(begin, end);
|
|
Subranges::iterator si = _subranges.lower_bound(range);
|
|
if (si == _subranges.end()) {
|
|
if (!_subranges.empty()) {
|
|
si = _subranges.begin() + _subranges.size() - 1;
|
|
if ((*si)._end >= begin) {
|
|
// The new range shortens the last element of the array on the right.
|
|
end = min(end, (*si)._begin);
|
|
(*si)._end = end;
|
|
// It might also shorten it on the left; fall through.
|
|
} else {
|
|
// The new range is completely after the last element of the array.
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
// The new range is completely after the last element of the array.
|
|
return;
|
|
}
|
|
}
|
|
|
|
nassertv((*si)._end >= end);
|
|
|
|
if ((*si)._begin > end) {
|
|
if (si != _subranges.begin()) {
|
|
Subranges::iterator si2 = si;
|
|
--si2;
|
|
if ((*si2)._end >= begin) {
|
|
// The new range shortens an element within the array on the
|
|
// right (but does not intersect the next element).
|
|
end = min(end, (*si2)._begin);
|
|
(*si2)._end = end;
|
|
// It might also shorten it on the left; fall through.
|
|
si = si2;
|
|
} else {
|
|
// The new range does not intersect any elements in the array.
|
|
return;
|
|
}
|
|
} else {
|
|
// The new range does not intersect any elements in the array.
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if (end < (*si)._end) {
|
|
// We must split an element into two.
|
|
Subrange left_range((*si)._begin, begin);
|
|
(*si)._begin = end;
|
|
si = _subranges.insert_unverified(si, left_range);
|
|
}
|
|
|
|
// Check if the new range removes any elements to the left.
|
|
while (begin <= (*si)._begin) {
|
|
if (si == _subranges.begin()) {
|
|
_subranges.erase(si);
|
|
return;
|
|
}
|
|
Subranges::iterator si2 = si;
|
|
--si2;
|
|
_subranges.erase(si);
|
|
si = si2;
|
|
}
|
|
|
|
(*si)._end = min((*si)._end, begin);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_has_any
|
|
// Access: Private
|
|
// Description: Returns true if any of the consecutive range of
|
|
// integers beginning at begin, but not including end,
|
|
// appear in the array. Note that this will return
|
|
// false for an empty range.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool SparseArray::
|
|
do_has_any(int begin, int end) const {
|
|
if (begin >= end) {
|
|
// Empty range.
|
|
return false;
|
|
}
|
|
|
|
Subrange range(begin, end);
|
|
Subranges::const_iterator si = _subranges.lower_bound(range);
|
|
if (si != _subranges.end() && end > (*si)._begin) {
|
|
return true;
|
|
}
|
|
if (si != _subranges.begin()) {
|
|
--si;
|
|
if (begin < (*si)._end) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_has_all
|
|
// Access: Private
|
|
// Description: Returns true if all of the consecutive range of
|
|
// integers beginning at begin, but not including end,
|
|
// appear in the array. Note that this will return
|
|
// true for an empty range.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool SparseArray::
|
|
do_has_all(int begin, int end) const {
|
|
if (begin >= end) {
|
|
// Empty range.
|
|
return true;
|
|
}
|
|
|
|
Subrange range(begin, end);
|
|
Subranges::const_iterator si = _subranges.lower_bound(range);
|
|
if (si != _subranges.end() && begin >= (*si)._begin) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_intersection
|
|
// Access: Private
|
|
// Description: Removes from this array all of the elements that do
|
|
// not appear in the other one.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_intersection(const SparseArray &other) {
|
|
if (_subranges.empty()) {
|
|
return;
|
|
}
|
|
if (other._subranges.empty()) {
|
|
_subranges.clear();
|
|
return;
|
|
}
|
|
|
|
int my_begin = (*_subranges.begin())._begin;
|
|
int other_begin = (*other._subranges.begin())._begin;
|
|
do_remove_range(my_begin, other_begin);
|
|
|
|
for (size_t i = 0; i < other._subranges.size() - 1; ++i) {
|
|
do_remove_range(other._subranges[i]._end, other._subranges[i + 1]._begin);
|
|
}
|
|
|
|
int my_end = (*(_subranges.begin() + _subranges.size() - 1))._end;
|
|
int other_end = (*(other._subranges.begin() + other._subranges.size() - 1))._end;
|
|
do_remove_range(other_end, my_end);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_union
|
|
// Access: Private
|
|
// Description: Adds to this array all of the elements that also
|
|
// appear in the other one.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_union(const SparseArray &other) {
|
|
Subranges::const_iterator si;
|
|
for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
|
|
do_add_range((*si)._begin, (*si)._end);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_intersection_neg
|
|
// Access: Private
|
|
// Description: Removes from this array all of the elements that also
|
|
// appear in the other one.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_intersection_neg(const SparseArray &other) {
|
|
Subranges::const_iterator si;
|
|
for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
|
|
do_remove_range((*si)._begin, (*si)._end);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::do_shift
|
|
// Access: Private
|
|
// Description: Shifts all the elements in the array by the indicated
|
|
// amount.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
do_shift(int offset) {
|
|
if (offset != 0) {
|
|
Subranges::iterator si;
|
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
|
(*si)._begin += offset;
|
|
(*si)._end += offset;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::write_datagram
|
|
// Access: Public
|
|
// Description: Writes the contents of this object to the datagram
|
|
// for shipping out to a Bam file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
write_datagram(BamWriter *manager, Datagram &dg) const {
|
|
dg.add_uint32(_subranges.size());
|
|
Subranges::const_iterator si;
|
|
for (si = _subranges.begin(); si != _subranges.end(); ++si) {
|
|
dg.add_int32((*si)._begin);
|
|
dg.add_int32((*si)._end);
|
|
}
|
|
dg.add_bool(_inverse);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: SparseArray::read_datagram
|
|
// Access: Public
|
|
// Description: Reads the object that was previously written to a Bam
|
|
// file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void SparseArray::
|
|
read_datagram(DatagramIterator &scan, BamReader *manager) {
|
|
size_t num_subranges = scan.get_uint32();
|
|
_subranges.reserve(num_subranges);
|
|
for (size_t i = 0; i < num_subranges; ++i) {
|
|
int begin = scan.get_int32();
|
|
int end = scan.get_int32();
|
|
_subranges.push_back(Subrange(begin, end));
|
|
}
|
|
_inverse = scan.get_bool();
|
|
}
|