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