xref: /aosp_15_r20/external/pdfium/third_party/bigint/NumberlikeArray.hh (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 Worker void 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 Worker void 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 Worker NumberlikeArray<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 Worker NumberlikeArray<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 Worker NumberlikeArray<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 Worker bool 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