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