Panda3D
sparseArray.cxx
1 // Filename: sparseArray.cxx
2 // Created by: drose (14Feb07)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "sparseArray.h"
16 #include "bitArray.h"
17 #include "datagram.h"
18 #include "datagramIterator.h"
19 
20 TypeHandle SparseArray::_type_handle;
21 
22 ////////////////////////////////////////////////////////////////////
23 // Function: SparseArray::Constructor (from BitArray)
24 // Access: Published
25 // Description:
26 ////////////////////////////////////////////////////////////////////
27 SparseArray::
28 SparseArray(const BitArray &from) {
29  bool empty_bit = from.get_highest_bits();
30  _inverse = empty_bit;
31 
32  int begin = 0;
33  bool current_state = from.get_bit(0);
34  int i = 0;
35 
36  // By including get_num_bits()--one more than the last bit--in this
37  // traversal, we guarantee that we will end on the empty_bit state
38  // (because the last bit we visit will be one of the highest_bits).
39  while (i <= from.get_num_bits()) {
40  if (from.get_bit(i) != current_state) {
41  // End of a run.
42  if (current_state != empty_bit) {
43  Subrange range(begin, i);
44  _subranges.push_back(range);
45  }
46  begin = i;
47  current_state = !current_state;
48  }
49  ++i;
50  }
51 
52  nassertv(current_state == empty_bit);
53 }
54 
55 ////////////////////////////////////////////////////////////////////
56 // Function: SparseArray::get_num_on_bits
57 // Access: Published
58 // Description: Returns the number of bits that are set to 1 in the
59 // array. Returns -1 if there are an infinite number of
60 // 1 bits.
61 ////////////////////////////////////////////////////////////////////
62 int SparseArray::
63 get_num_on_bits() const {
64  if (_inverse) {
65  return -1;
66  }
67 
68  int result = 0;
69  Subranges::const_iterator si;
70  for (si = _subranges.begin(); si != _subranges.end(); ++si) {
71  result += (*si)._end - (*si)._begin;
72  }
73 
74  return result;
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: SparseArray::get_num_off_bits
79 // Access: Published
80 // Description: Returns the number of bits that are set to 0 in the
81 // array. Returns -1 if there are an infinite number of
82 // 0 bits.
83 ////////////////////////////////////////////////////////////////////
84 int SparseArray::
86  if (!_inverse) {
87  return -1;
88  }
89 
90  int result = 0;
91  Subranges::const_iterator si;
92  for (si = _subranges.begin(); si != _subranges.end(); ++si) {
93  result += (*si)._end - (*si)._begin;
94  }
95 
96  return result;
97 }
98 
99 ////////////////////////////////////////////////////////////////////
100 // Function: SparseArray::get_lowest_on_bit
101 // Access: Published
102 // Description: Returns the index of the lowest 1 bit in the array.
103 // Returns -1 if there are no 1 bits or if there are an
104 // infinite number of 1 bits.
105 ////////////////////////////////////////////////////////////////////
106 int SparseArray::
108  if (_inverse) {
109  return -1;
110  }
111 
112  if (_subranges.empty()) {
113  return -1;
114  }
115 
116  return _subranges[0]._begin;
117 }
118 
119 ////////////////////////////////////////////////////////////////////
120 // Function: SparseArray::get_lowest_off_bit
121 // Access: Published
122 // Description: Returns the index of the lowest 0 bit in the array.
123 // Returns -1 if there are no 0 bits or if there are an
124 // infinite number of 1 bits.
125 ////////////////////////////////////////////////////////////////////
126 int SparseArray::
128  if (!_inverse) {
129  return -1;
130  }
131 
132  if (_subranges.empty()) {
133  return -1;
134  }
135 
136  return _subranges[0]._begin;
137 }
138 
139 ////////////////////////////////////////////////////////////////////
140 // Function: SparseArray::get_highest_on_bit
141 // Access: Published
142 // Description: Returns the index of the highest 1 bit in the array.
143 // Returns -1 if there are no 1 bits or if there an
144 // infinite number of 1 bits.
145 ////////////////////////////////////////////////////////////////////
146 int SparseArray::
148  if (_inverse) {
149  return -1;
150  }
151 
152  if (_subranges.empty()) {
153  return -1;
154  }
155 
156  return _subranges[_subranges.size() - 1]._end - 1;
157 }
158 
159 ////////////////////////////////////////////////////////////////////
160 // Function: SparseArray::get_highest_off_bit
161 // Access: Published
162 // Description: Returns the index of the highest 0 bit in the array.
163 // Returns -1 if there are no 0 bits or if there an
164 // infinite number of 1 bits.
165 ////////////////////////////////////////////////////////////////////
166 int SparseArray::
168  if (!_inverse) {
169  return -1;
170  }
171 
172  if (_subranges.empty()) {
173  return -1;
174  }
175 
176  return _subranges[_subranges.size() - 1]._end - 1;
177 }
178 
179 ////////////////////////////////////////////////////////////////////
180 // Function: SparseArray::get_next_higher_different_bit
181 // Access: Published
182 // Description: Returns the index of the next bit in the array, above
183 // low_bit, whose value is different that the value of
184 // low_bit. Returns low_bit again if all bits higher
185 // than low_bit have the same value.
186 //
187 // This can be used to quickly iterate through all of
188 // the bits in the array.
189 ////////////////////////////////////////////////////////////////////
190 int SparseArray::
191 get_next_higher_different_bit(int low_bit) const {
192  Subrange range(low_bit, low_bit + 1);
193  Subranges::const_iterator si = _subranges.lower_bound(range);
194  if (si == _subranges.end()) {
195  // That was the end of the array.
196  return low_bit;
197  }
198 
199  if (low_bit >= (*si)._begin) {
200  return (*si)._end;
201  }
202 
203  int next = (*si)._begin;
204 
205  if (si != _subranges.begin()) {
206  --si;
207  if (low_bit < (*si)._end) {
208  return (*si)._end;
209  }
210  }
211 
212  return next;
213 }
214 
215 ////////////////////////////////////////////////////////////////////
216 // Function: SparseArray::has_bits_in_common
217 // Access: Published
218 // Description: Returns true if this SparseArray has any "one" bits in
219 // common with the other one, false otherwise.
220 //
221 // This is equivalent to (array & other) != 0, but may
222 // be faster.
223 ////////////////////////////////////////////////////////////////////
224 bool SparseArray::
225 has_bits_in_common(const SparseArray &other) const {
226  if (_inverse && other._inverse) {
227  // Yup, in fact we have an infinite number of bits in common.
228  return true;
229  }
230 
231  if (_inverse != other._inverse) {
232  // We'll handle this tricky case the lazy way.
233  return !(*this & other).is_zero();
234  }
235 
236  // Actually, we'll handle this easy case the lazy way too. Maybe
237  // later we'll do this smarter.
238  return !(*this & other).is_zero();
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: SparseArray::output
243 // Access: Published
244 // Description:
245 ////////////////////////////////////////////////////////////////////
246 void SparseArray::
247 output(ostream &out) const {
248  out << "[ ";
249  if (_inverse) {
250  out << "all except: ";
251  }
252  Subranges::const_iterator si;
253  for (si = _subranges.begin(); si != _subranges.end(); ++si) {
254  if ((*si)._end == (*si)._begin + 1) {
255  // A single element.
256  out << (*si)._begin << ", ";
257  } else {
258  // A range of elements.
259  out << (*si)._begin << "-" << ((*si)._end - 1) << ", ";
260  }
261  }
262  out << "]";
263 }
264 
265 ////////////////////////////////////////////////////////////////////
266 // Function: SparseArray::compare_to
267 // Access: Published
268 // Description: Returns a number less than zero if this SparseArray
269 // sorts before the indicated other SparseArray, greater
270 // than zero if it sorts after, or 0 if they are
271 // equivalent. This is based on the same ordering
272 // defined by operator <.
273 ////////////////////////////////////////////////////////////////////
274 int SparseArray::
275 compare_to(const SparseArray &other) const {
276  if (_inverse != other._inverse) {
277  return _inverse ? 1 : -1;
278  }
279 
280  Subranges::const_reverse_iterator ai = _subranges.rbegin();
281  Subranges::const_reverse_iterator bi = other._subranges.rbegin();
282 
283  while (ai != _subranges.rend() && bi != other._subranges.rend()) {
284  if ((*ai)._end < (*bi)._end) {
285  // B is higher.
286  return -1;
287  } else if ((*bi)._end < (*ai)._end) {
288  // A is higher.
289  return 1;
290  } else if ((*ai)._begin < (*bi)._begin) {
291  // A is higher.
292  return 1;
293  } else if ((*bi)._begin < (*ai)._begin) {
294  // B is higher.
295  return -1;
296  }
297 
298  --ai;
299  --bi;
300  }
301 
302  if (ai != _subranges.rend()) {
303  // A is higher.
304  return 1;
305  }
306  if (bi != other._subranges.rend()) {
307  // B is higher.
308  return -1;
309  }
310 
311  return 0;
312 }
313 
314 ////////////////////////////////////////////////////////////////////
315 // Function: SparseArray::operator &=
316 // Access: Published
317 // Description:
318 ////////////////////////////////////////////////////////////////////
319 void SparseArray::
320 operator &= (const SparseArray &other) {
321  // We do this the slow and stupid way. This could be done much
322  // better with a little effort, but I'm not at all sure it's worth
323  // the effort. If you need fast boolean operations, you should
324  // probably be using a BitArray.
325 
326  if (_inverse && other._inverse) {
327  do_union(other);
328 
329  } else if (!_inverse && !other._inverse) {
330  do_intersection(other);
331 
332  } else if (_inverse && !other._inverse) {
333  // a & b == b & a
334  (*this) = other & (*this);
335 
336  } else if (!_inverse && other._inverse) {
337  do_intersection_neg(other);
338 
339  } else {
340  // TODO.
341  nassertv(false);
342  }
343 }
344 
345 ////////////////////////////////////////////////////////////////////
346 // Function: SparseArray::operator |=
347 // Access: Published
348 // Description:
349 ////////////////////////////////////////////////////////////////////
350 void SparseArray::
351 operator |= (const SparseArray &other) {
352  // We do this the slow and stupid way. This could be done much
353  // better with a little effort, but I'm not at all sure it's worth
354  // the effort. If you need fast boolean operations, you should
355  // probably be using a BitArray.
356 
357  if (_inverse && other._inverse) {
358  do_intersection(other);
359 
360  } else if (!_inverse && !other._inverse) {
361  do_union(other);
362 
363  } else if (_inverse && !other._inverse) {
364  do_intersection_neg(other);
365 
366  } else if (!_inverse && other._inverse) {
367  // a | b == b | a
368  (*this) = other | (*this);
369 
370  } else {
371  nassertv(false);
372  }
373 }
374 
375 ////////////////////////////////////////////////////////////////////
376 // Function: SparseArray::operator ^=
377 // Access: Published
378 // Description:
379 ////////////////////////////////////////////////////////////////////
380 void SparseArray::
381 operator ^= (const SparseArray &other) {
382  // We do this the slow and stupid way. This could be done much
383  // better with a little effort, but I'm not at all sure it's worth
384  // the effort. If you need fast boolean operations, you should
385  // probably be using a BitArray.
386 
387  (*this) = ((*this) | other) & ~((*this) & other);
388 }
389 
390 ////////////////////////////////////////////////////////////////////
391 // Function: SparseArray::do_add_range
392 // Access: Private
393 // Description: Adds the consecutive range of integers beginning at
394 // begin, but not including end, to the array. If this
395 // range overlaps with another range already in the
396 // array, the result is the union.
397 ////////////////////////////////////////////////////////////////////
398 void SparseArray::
399 do_add_range(int begin, int end) {
400  if (begin >= end) {
401  // Empty range.
402  return;
403  }
404 
405  Subrange range(begin, end);
406  Subranges::iterator si = _subranges.lower_bound(range);
407  if (si == _subranges.end()) {
408  if (!_subranges.empty()) {
409  si = _subranges.begin() + _subranges.size() - 1;
410  if ((*si)._end >= begin) {
411  // The new range expands the last element of the array to the right.
412  (*si)._end = end;
413  // It might also expand it to the left; fall through.
414  } else {
415  // The new range is completely after the last element of the array.
416  _subranges.push_back(range);
417  return;
418  }
419 
420  } else {
421  // The new range is completely after the last element of the array.
422  _subranges.push_back(range);
423  return;
424  }
425  }
426 
427  nassertv((*si)._end >= end);
428 
429  if ((*si)._begin > end) {
430  if (si != _subranges.begin()) {
431  Subranges::iterator si2 = si;
432  --si2;
433  if ((*si2)._end >= begin) {
434  // The new range expands an element within the array to the
435  // right (but does not intersect the next element).
436  (*si2)._end = end;
437  // It might also expand it to the left; fall through.
438  si = si2;
439  } else {
440  // The new range does not intersect any elements in the array.
441  _subranges.insert_unverified(si, range);
442  return;
443  }
444  } else {
445  // The new range does not intersect any elements in the array.
446  _subranges.insert_unverified(si, range);
447  return;
448  }
449  }
450 
451  // Check if the new range overlaps with any elements to the left.
452  while (si != _subranges.begin()) {
453  Subranges::iterator si2 = si;
454  --si2;
455  if ((*si2)._end >= begin) {
456  // The new range straddles two elements, so they get combined.
457  (*si2)._end = (*si)._end;
458  _subranges.erase(si);
459  } else {
460  // Stop here.
461  break;
462  }
463  si = si2;
464  }
465 
466  if ((*si)._begin > begin) {
467  // The new range expands an element to the left.
468  (*si)._begin = begin;
469  }
470 }
471 
472 ////////////////////////////////////////////////////////////////////
473 // Function: SparseArray::do_remove_range
474 // Access: Private
475 // Description: Removes the consecutive range of integers beginning
476 // at begin, but not including end, from the array.
477 ////////////////////////////////////////////////////////////////////
478 void SparseArray::
479 do_remove_range(int begin, int end) {
480  if (begin >= end) {
481  // Empty range.
482  return;
483  }
484 
485  Subrange range(begin, end);
486  Subranges::iterator si = _subranges.lower_bound(range);
487  if (si == _subranges.end()) {
488  if (!_subranges.empty()) {
489  si = _subranges.begin() + _subranges.size() - 1;
490  if ((*si)._end >= begin) {
491  // The new range shortens the last element of the array on the right.
492  end = min(end, (*si)._begin);
493  (*si)._end = end;
494  // It might also shorten it on the left; fall through.
495  } else {
496  // The new range is completely after the last element of the array.
497  return;
498  }
499 
500  } else {
501  // The new range is completely after the last element of the array.
502  return;
503  }
504  }
505 
506  nassertv((*si)._end >= end);
507 
508  if ((*si)._begin > end) {
509  if (si != _subranges.begin()) {
510  Subranges::iterator si2 = si;
511  --si2;
512  if ((*si2)._end >= begin) {
513  // The new range shortens an element within the array on the
514  // right (but does not intersect the next element).
515  end = min(end, (*si2)._begin);
516  (*si2)._end = end;
517  // It might also shorten it on the left; fall through.
518  si = si2;
519  } else {
520  // The new range does not intersect any elements in the array.
521  return;
522  }
523  } else {
524  // The new range does not intersect any elements in the array.
525  return;
526  }
527  }
528 
529 
530  if (end < (*si)._end) {
531  // We must split an element into two.
532  Subrange left_range((*si)._begin, begin);
533  (*si)._begin = end;
534  si = _subranges.insert_unverified(si, left_range);
535  }
536 
537  // Check if the new range removes any elements to the left.
538  while (begin <= (*si)._begin) {
539  if (si == _subranges.begin()) {
540  _subranges.erase(si);
541  return;
542  }
543  Subranges::iterator si2 = si;
544  --si2;
545  _subranges.erase(si);
546  si = si2;
547  }
548 
549  (*si)._end = min((*si)._end, begin);
550 }
551 
552 ////////////////////////////////////////////////////////////////////
553 // Function: SparseArray::do_has_any
554 // Access: Private
555 // Description: Returns true if any of the consecutive range of
556 // integers beginning at begin, but not including end,
557 // appear in the array. Note that this will return
558 // false for an empty range.
559 ////////////////////////////////////////////////////////////////////
560 bool SparseArray::
561 do_has_any(int begin, int end) const {
562  if (begin >= end) {
563  // Empty range.
564  return false;
565  }
566 
567  Subrange range(begin, end);
568  Subranges::const_iterator si = _subranges.lower_bound(range);
569  if (si != _subranges.end() && end > (*si)._begin) {
570  return true;
571  }
572  if (si != _subranges.begin()) {
573  --si;
574  if (begin < (*si)._end) {
575  return true;
576  }
577  }
578 
579  return false;
580 }
581 
582 ////////////////////////////////////////////////////////////////////
583 // Function: SparseArray::do_has_all
584 // Access: Private
585 // Description: Returns true if all of the consecutive range of
586 // integers beginning at begin, but not including end,
587 // appear in the array. Note that this will return
588 // true for an empty range.
589 ////////////////////////////////////////////////////////////////////
590 bool SparseArray::
591 do_has_all(int begin, int end) const {
592  if (begin >= end) {
593  // Empty range.
594  return true;
595  }
596 
597  Subrange range(begin, end);
598  Subranges::const_iterator si = _subranges.lower_bound(range);
599  if (si != _subranges.end() && begin >= (*si)._begin) {
600  return true;
601  }
602 
603  return false;
604 }
605 
606 ////////////////////////////////////////////////////////////////////
607 // Function: SparseArray::do_intersection
608 // Access: Private
609 // Description: Removes from this array all of the elements that do
610 // not appear in the other one.
611 ////////////////////////////////////////////////////////////////////
612 void SparseArray::
613 do_intersection(const SparseArray &other) {
614  if (_subranges.empty()) {
615  return;
616  }
617  if (other._subranges.empty()) {
618  _subranges.clear();
619  return;
620  }
621 
622  int my_begin = (*_subranges.begin())._begin;
623  int other_begin = (*other._subranges.begin())._begin;
624  do_remove_range(my_begin, other_begin);
625 
626  for (size_t i = 0; i < other._subranges.size() - 1; ++i) {
627  do_remove_range(other._subranges[i]._end, other._subranges[i + 1]._begin);
628  }
629 
630  int my_end = (*(_subranges.begin() + _subranges.size() - 1))._end;
631  int other_end = (*(other._subranges.begin() + other._subranges.size() - 1))._end;
632  do_remove_range(other_end, my_end);
633 }
634 
635 ////////////////////////////////////////////////////////////////////
636 // Function: SparseArray::do_union
637 // Access: Private
638 // Description: Adds to this array all of the elements that also
639 // appear in the other one.
640 ////////////////////////////////////////////////////////////////////
641 void SparseArray::
642 do_union(const SparseArray &other) {
643  Subranges::const_iterator si;
644  for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
645  do_add_range((*si)._begin, (*si)._end);
646  }
647 }
648 
649 ////////////////////////////////////////////////////////////////////
650 // Function: SparseArray::do_intersection_neg
651 // Access: Private
652 // Description: Removes from this array all of the elements that also
653 // appear in the other one.
654 ////////////////////////////////////////////////////////////////////
655 void SparseArray::
656 do_intersection_neg(const SparseArray &other) {
657  Subranges::const_iterator si;
658  for (si = other._subranges.begin(); si != other._subranges.end(); ++si) {
659  do_remove_range((*si)._begin, (*si)._end);
660  }
661 }
662 
663 ////////////////////////////////////////////////////////////////////
664 // Function: SparseArray::do_shift
665 // Access: Private
666 // Description: Shifts all the elements in the array by the indicated
667 // amount.
668 ////////////////////////////////////////////////////////////////////
669 void SparseArray::
670 do_shift(int offset) {
671  if (offset != 0) {
672  Subranges::iterator si;
673  for (si = _subranges.begin(); si != _subranges.end(); ++si) {
674  (*si)._begin += offset;
675  (*si)._end += offset;
676  }
677  }
678 }
679 
680 ////////////////////////////////////////////////////////////////////
681 // Function: SparseArray::write_datagram
682 // Access: Public
683 // Description: Writes the contents of this object to the datagram
684 // for shipping out to a Bam file.
685 ////////////////////////////////////////////////////////////////////
686 void SparseArray::
687 write_datagram(BamWriter *manager, Datagram &dg) const {
688  dg.add_uint32(_subranges.size());
689  Subranges::const_iterator si;
690  for (si = _subranges.begin(); si != _subranges.end(); ++si) {
691  dg.add_int32((*si)._begin);
692  dg.add_int32((*si)._end);
693  }
694  dg.add_bool(_inverse);
695 }
696 
697 ////////////////////////////////////////////////////////////////////
698 // Function: SparseArray::read_datagram
699 // Access: Public
700 // Description: Reads the object that was previously written to a Bam
701 // file.
702 ////////////////////////////////////////////////////////////////////
703 void SparseArray::
705  size_t num_subranges = scan.get_uint32();
706  _subranges.reserve(num_subranges);
707  for (size_t i = 0; i < num_subranges; ++i) {
708  int begin = scan.get_int32();
709  int end = scan.get_int32();
710  _subranges.push_back(Subrange(begin, end));
711  }
712  _inverse = scan.get_bool();
713 }
This class records a set of integers, where each integer is either present or not present in the set...
Definition: sparseArray.h:49
int get_num_bits() const
Returns the current number of possibly different bits in this array.
Definition: bitArray.I:194
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the array.
bool get_bool()
Extracts a boolean value.
bool get_highest_bits() const
Returns true if the infinite set of bits beyond get_num_bits() are all on, or false of they are all o...
Definition: bitArray.I:281
int get_lowest_off_bit() const
Returns the index of the lowest 0 bit in the array.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
Definition: bitArray.I:207
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
size_type_0 size() const
Returns the number of elements in the ordered vector.
void clear()
Removes all elements from the ordered vector.
void write_datagram(BamWriter *manager, Datagram &dg) const
Writes the contents of this object to the datagram for shipping out to a Bam file.
int get_next_higher_different_bit(int low_bit) const
Returns the index of the next bit in the array, above low_bit, whose value is different that the valu...
int get_num_off_bits() const
Returns the number of bits that are set to 0 in the array.
Definition: sparseArray.cxx:85
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
bool is_zero() const
Returns true if the entire bitmask is zero, false otherwise.
Definition: sparseArray.I:246
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
PN_int32 get_int32()
Extracts a signed 32-bit integer.
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
void reserve(size_type_0 n)
Informs the vector of a planned change in size; ensures that the capacity of the vector is greater th...
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
int get_highest_on_bit() const
Returns the index of the highest 1 bit in the array.
A dynamic array with an unlimited number of bits.
Definition: bitArray.h:42
iterator_0 insert_unverified(iterator_0 position, const value_type_0 &key)
Inserts the indicated key into the ordered vector at the indicated place.
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:118
reverse_iterator_0 rbegin()
Returns the iterator that marks the first element in the ordered vector, when viewed in reverse order...
int get_highest_off_bit() const
Returns the index of the highest 0 bit in the array.
bool has_bits_in_common(const SparseArray &other) const
Returns true if this SparseArray has any "one" bits in common with the other one, false otherwise...
static SparseArray range(int low_bit, int size)
Returns a SparseArray whose size bits, beginning at low_bit, are on.
Definition: sparseArray.I:103
int compare_to(const SparseArray &other) const
Returns a number less than zero if this SparseArray sorts before the indicated other SparseArray...
void push_back(const value_type_0 &key)
Adds the new element to the end of the vector without regard for proper sorting.
reverse_iterator_0 rend()
Returns the iterator that marks the end of the ordered vector, when viewed in reverse order...
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:159
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
void read_datagram(DatagramIterator &scan, BamReader *manager)
Reads the object that was previously written to a Bam file.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
Definition: sparseArray.cxx:63