|  | // Copyright 2014 PDFium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Original code by Matt McCutchen, see the LICENSE file. | 
|  |  | 
|  | #ifndef NUMBERLIKEARRAY_H | 
|  | #define NUMBERLIKEARRAY_H | 
|  |  | 
|  | #include <stdlib.h> // abort() | 
|  | // Make sure we have NULL. | 
|  | #ifndef NULL | 
|  | #define NULL 0 | 
|  | #endif | 
|  |  | 
|  | /* A NumberlikeArray<Blk> object holds a heap-allocated array of Blk with a | 
|  | * length and a capacity and provides basic memory management features. | 
|  | * BigUnsigned and BigUnsignedInABase both subclass it. | 
|  | * | 
|  | * NumberlikeArray provides no information hiding.  Subclasses should use | 
|  | * nonpublic inheritance and manually expose members as desired using | 
|  | * declarations like this: | 
|  | * | 
|  | * public: | 
|  | *     NumberlikeArray< the-type-argument >::getLength; | 
|  | */ | 
|  | template <class Blk> | 
|  | class NumberlikeArray { | 
|  | public: | 
|  |  | 
|  | // Type for the index of a block in the array | 
|  | typedef unsigned int Index; | 
|  | // The number of bits in a block, defined below. | 
|  | static const unsigned int N; | 
|  |  | 
|  | // The current allocated capacity of this NumberlikeArray (in blocks) | 
|  | Index cap; | 
|  | // The actual length of the value stored in this NumberlikeArray (in blocks) | 
|  | Index len; | 
|  | // Heap-allocated array of the blocks (can be NULL if len == 0) | 
|  | Blk *blk; | 
|  |  | 
|  | // Constructs a ``zero'' NumberlikeArray with the given capacity. | 
|  | NumberlikeArray(Index c) : cap(c), len(0) { | 
|  | blk = (cap > 0) ? (new Blk[cap]) : NULL; | 
|  | } | 
|  |  | 
|  | /* Constructs a zero NumberlikeArray without allocating a backing array. | 
|  | * A subclass that doesn't know the needed capacity at initialization | 
|  | * time can use this constructor and then overwrite blk without first | 
|  | * deleting it. */ | 
|  | NumberlikeArray() : cap(0), len(0) { | 
|  | blk = NULL; | 
|  | } | 
|  |  | 
|  | // Destructor.  Note that `delete NULL' is a no-op. | 
|  | ~NumberlikeArray() { | 
|  | delete [] blk; | 
|  | } | 
|  |  | 
|  | /* Ensures that the array has at least the requested capacity; may | 
|  | * destroy the contents. */ | 
|  | void allocate(Index c); | 
|  |  | 
|  | /* Ensures that the array has at least the requested capacity; does not | 
|  | * destroy the contents. */ | 
|  | void allocateAndCopy(Index c); | 
|  |  | 
|  | // Copy constructor | 
|  | NumberlikeArray(const NumberlikeArray<Blk> &x); | 
|  |  | 
|  | // Assignment operator | 
|  | NumberlikeArray<Blk>& operator=(const NumberlikeArray<Blk> &x); | 
|  |  | 
|  | // Constructor that copies from a given array of blocks | 
|  | NumberlikeArray(const Blk *b, Index blen); | 
|  |  | 
|  | // ACCESSORS | 
|  | Index getCapacity()     const { return cap;      } | 
|  | Index getLength()       const { return len;      } | 
|  | Blk   getBlock(Index i) const { return blk[i];   } | 
|  | bool  isEmpty()         const { return len == 0; } | 
|  |  | 
|  | /* Equality comparison: checks if both objects have the same length and | 
|  | * equal (==) array elements to that length.  Subclasses may wish to | 
|  | * override. */ | 
|  | bool operator ==(const NumberlikeArray<Blk> &x) const; | 
|  |  | 
|  | bool operator !=(const NumberlikeArray<Blk> &x) const { | 
|  | return !operator ==(x); | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* BEGIN TEMPLATE DEFINITIONS.  They are present here so that source files that | 
|  | * include this header file can generate the necessary real definitions. */ | 
|  |  | 
|  | template <class Blk> | 
|  | const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk); | 
|  |  | 
|  | template <class Blk> | 
|  | void NumberlikeArray<Blk>::allocate(Index c) { | 
|  | // If the requested capacity is more than the current capacity... | 
|  | if (c > cap) { | 
|  | // Delete the old number array | 
|  | delete [] blk; | 
|  | // Allocate the new array | 
|  | cap = c; | 
|  | blk = new Blk[cap]; | 
|  | } | 
|  | } | 
|  |  | 
|  | template <class Blk> | 
|  | void NumberlikeArray<Blk>::allocateAndCopy(Index c) { | 
|  | // If the requested capacity is more than the current capacity... | 
|  | if (c > cap) { | 
|  | Blk *oldBlk = blk; | 
|  | // Allocate the new number array | 
|  | cap = c; | 
|  | blk = new Blk[cap]; | 
|  | // Copy number blocks | 
|  | Index i; | 
|  | for (i = 0; i < len; i++) | 
|  | blk[i] = oldBlk[i]; | 
|  | // Delete the old array | 
|  | delete [] oldBlk; | 
|  | } | 
|  | } | 
|  |  | 
|  | template <class Blk> | 
|  | NumberlikeArray<Blk>::NumberlikeArray(const NumberlikeArray<Blk> &x) | 
|  | : len(x.len) { | 
|  | // Create array | 
|  | cap = len; | 
|  | blk = new Blk[cap]; | 
|  | // Copy blocks | 
|  | Index i; | 
|  | for (i = 0; i < len; i++) | 
|  | blk[i] = x.blk[i]; | 
|  | } | 
|  |  | 
|  | template <class Blk> | 
|  | NumberlikeArray<Blk>& NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) { | 
|  | /* Calls like a = a have no effect; catch them before the aliasing | 
|  | * causes a problem */ | 
|  | if (this == &x) | 
|  | return *this; | 
|  | // Copy length | 
|  | len = x.len; | 
|  | // Expand array if necessary | 
|  | allocate(len); | 
|  | // Copy number blocks | 
|  | Index i; | 
|  | for (i = 0; i < len; i++) | 
|  | blk[i] = x.blk[i]; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <class Blk> | 
|  | NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen) | 
|  | : cap(blen), len(blen) { | 
|  | // Create array | 
|  | blk = new Blk[cap]; | 
|  | // Copy blocks | 
|  | Index i; | 
|  | for (i = 0; i < len; i++) | 
|  | blk[i] = b[i]; | 
|  | } | 
|  |  | 
|  | template <class Blk> | 
|  | bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const { | 
|  | if (len != x.len) | 
|  | // Definitely unequal. | 
|  | return false; | 
|  | else { | 
|  | // Compare corresponding blocks one by one. | 
|  | Index i; | 
|  | for (i = 0; i < len; i++) | 
|  | if (blk[i] != x.blk[i]) | 
|  | return false; | 
|  | // No blocks differed, so the objects are equal. | 
|  | return true; | 
|  | } | 
|  | } | 
|  |  | 
|  | #endif |