NumberlikeArray.hh 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #ifndef NUMBERLIKEARRAY_H
  2. #define NUMBERLIKEARRAY_H
  3. // Make sure we have NULL.
  4. #ifndef NULL
  5. #define NULL 0
  6. #endif
  7. /* A NumberlikeArray<Blk> object holds a heap-allocated array of Blk with a
  8. * length and a capacity and provides basic memory management features.
  9. * BigUnsigned and BigUnsignedInABase both subclass it.
  10. *
  11. * NumberlikeArray provides no information hiding. Subclasses should use
  12. * nonpublic inheritance and manually expose members as desired using
  13. * declarations like this:
  14. *
  15. * public:
  16. * NumberlikeArray< the-type-argument >::getLength;
  17. */
  18. template <class Blk>
  19. class NumberlikeArray {
  20. public:
  21. // Type for the index of a block in the array
  22. typedef unsigned int Index;
  23. // The number of bits in a block, defined below.
  24. static const unsigned int N;
  25. // The current allocated capacity of this NumberlikeArray (in blocks)
  26. Index cap;
  27. // The actual length of the value stored in this NumberlikeArray (in blocks)
  28. Index len;
  29. // Heap-allocated array of the blocks (can be NULL if len == 0)
  30. Blk *blk;
  31. // Constructs a ``zero'' NumberlikeArray with the given capacity.
  32. NumberlikeArray(Index c) : cap(c), len(0) {
  33. blk = (cap > 0) ? (new Blk[cap]) : NULL;
  34. }
  35. /* Constructs a zero NumberlikeArray without allocating a backing array.
  36. * A subclass that doesn't know the needed capacity at initialization
  37. * time can use this constructor and then overwrite blk without first
  38. * deleting it. */
  39. NumberlikeArray() : cap(0), len(0) {
  40. blk = NULL;
  41. }
  42. // Destructor. Note that `delete NULL' is a no-op.
  43. ~NumberlikeArray() {
  44. delete [] blk;
  45. }
  46. /* Ensures that the array has at least the requested capacity; may
  47. * destroy the contents. */
  48. void allocate(Index c);
  49. /* Ensures that the array has at least the requested capacity; does not
  50. * destroy the contents. */
  51. void allocateAndCopy(Index c);
  52. // Copy constructor
  53. NumberlikeArray(const NumberlikeArray<Blk> &x);
  54. // Assignment operator
  55. void operator=(const NumberlikeArray<Blk> &x);
  56. // Constructor that copies from a given array of blocks
  57. NumberlikeArray(const Blk *b, Index blen);
  58. // ACCESSORS
  59. Index getCapacity() const { return cap; }
  60. Index getLength() const { return len; }
  61. Blk getBlock(Index i) const { return blk[i]; }
  62. bool isEmpty() const { return len == 0; }
  63. /* Equality comparison: checks if both objects have the same length and
  64. * equal (==) array elements to that length. Subclasses may wish to
  65. * override. */
  66. bool operator ==(const NumberlikeArray<Blk> &x) const;
  67. bool operator !=(const NumberlikeArray<Blk> &x) const {
  68. return !operator ==(x);
  69. }
  70. };
  71. /* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that
  72. * include this header file can generate the necessary real definitions. */
  73. template <class Blk>
  74. const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk);
  75. template <class Blk>
  76. void NumberlikeArray<Blk>::allocate(Index c) {
  77. // If the requested capacity is more than the current capacity...
  78. if (c > cap) {
  79. // Delete the old number array
  80. delete [] blk;
  81. // Allocate the new array
  82. cap = c;
  83. blk = new Blk[cap];
  84. }
  85. }
  86. template <class Blk>
  87. void NumberlikeArray<Blk>::allocateAndCopy(Index c) {
  88. // If the requested capacity is more than the current capacity...
  89. if (c > cap) {
  90. Blk *oldBlk = blk;
  91. // Allocate the new number array
  92. cap = c;
  93. blk = new Blk[cap];
  94. // Copy number blocks
  95. Index i;
  96. for (i = 0; i < len; i++)
  97. blk[i] = oldBlk[i];
  98. // Delete the old array
  99. delete [] oldBlk;
  100. }
  101. }
  102. template <class Blk>
  103. NumberlikeArray<Blk>::NumberlikeArray(const NumberlikeArray<Blk> &x)
  104. : len(x.len) {
  105. // Create array
  106. cap = len;
  107. blk = new Blk[cap];
  108. // Copy blocks
  109. Index i;
  110. for (i = 0; i < len; i++)
  111. blk[i] = x.blk[i];
  112. }
  113. template <class Blk>
  114. void NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) {
  115. /* Calls like a = a have no effect; catch them before the aliasing
  116. * causes a problem */
  117. if (this == &x)
  118. return;
  119. // Copy length
  120. len = x.len;
  121. // Expand array if necessary
  122. allocate(len);
  123. // Copy number blocks
  124. Index i;
  125. for (i = 0; i < len; i++)
  126. blk[i] = x.blk[i];
  127. }
  128. template <class Blk>
  129. NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen)
  130. : cap(blen), len(blen) {
  131. // Create array
  132. blk = new Blk[cap];
  133. // Copy blocks
  134. Index i;
  135. for (i = 0; i < len; i++)
  136. blk[i] = b[i];
  137. }
  138. template <class Blk>
  139. bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const {
  140. if (len != x.len)
  141. // Definitely unequal.
  142. return false;
  143. else {
  144. // Compare corresponding blocks one by one.
  145. Index i;
  146. for (i = 0; i < len; i++)
  147. if (blk[i] != x.blk[i])
  148. return false;
  149. // No blocks differed, so the objects are equal.
  150. return true;
  151. }
  152. }
  153. #endif