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