| // 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 |