blob: df58daeff73b23cd56b315d705261ca137f05468 [file] [log] [blame]
Bo Xu8ad00402014-12-02 13:06:22 -08001// 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 */
27template <class Blk>
28class NumberlikeArray {
29public:
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
Andrew Weintraubd1fb2c52019-06-24 22:47:15 +000073 NumberlikeArray<Blk>& operator=(const NumberlikeArray<Blk> &x);
Bo Xu8ad00402014-12-02 13:06:22 -080074
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
97template <class Blk>
98const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk);
99
100template <class Blk>
101void 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
112template <class Blk>
113void 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
129template <class Blk>
130NumberlikeArray<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
141template <class Blk>
Andrew Weintraubd1fb2c52019-06-24 22:47:15 +0000142NumberlikeArray<Blk>& NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) {
Bo Xu8ad00402014-12-02 13:06:22 -0800143 /* Calls like a = a have no effect; catch them before the aliasing
144 * causes a problem */
145 if (this == &x)
Andrew Weintraubd1fb2c52019-06-24 22:47:15 +0000146 return *this;
Bo Xu8ad00402014-12-02 13:06:22 -0800147 // 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];
Andrew Weintraubd1fb2c52019-06-24 22:47:15 +0000155 return *this;
Bo Xu8ad00402014-12-02 13:06:22 -0800156}
157
158template <class Blk>
159NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen)
160 : cap(blen), len(blen) {
161 // Create array
162 blk = new Blk[cap];
163 // Copy blocks
164 Index i;
165 for (i = 0; i < len; i++)
166 blk[i] = b[i];
167}
168
169template <class Blk>
170bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const {
171 if (len != x.len)
172 // Definitely unequal.
173 return false;
174 else {
175 // Compare corresponding blocks one by one.
176 Index i;
177 for (i = 0; i < len; i++)
178 if (blk[i] != x.blk[i])
179 return false;
180 // No blocks differed, so the objects are equal.
181 return true;
182 }
183}
184
185#endif