Home | History | Annotate | Download | only in bigint
      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