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 BIGUNSIGNEDINABASE_H
8#define BIGUNSIGNEDINABASE_H
9
10#include "NumberlikeArray.hh"
11#include "BigUnsigned.hh"
12#include <string>
13
14/*
15 * A BigUnsignedInABase object represents a nonnegative integer of size limited
16 * only by available memory, represented in a user-specified base that can fit
17 * in an `unsigned short' (most can, and this saves memory).
18 *
19 * BigUnsignedInABase is intended as an intermediary class with little
20 * functionality of its own.  BigUnsignedInABase objects can be constructed
21 * from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.)
22 * and `std::string's (by switching digit values for appropriate characters).
23 *
24 * BigUnsignedInABase is similar to BigUnsigned.  Note the following:
25 *
26 * (1) They represent the number in exactly the same way, except that
27 * BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses
28 * ``blocks'' (or Blk).
29 *
30 * (2) Both use the management features of NumberlikeArray.  (In fact, my desire
31 * to add a BigUnsignedInABase class without duplicating a lot of code led me to
32 * introduce NumberlikeArray.)
33 *
34 * (3) The only arithmetic operation supported by BigUnsignedInABase is an
35 * equality test.  Use BigUnsigned for arithmetic.
36 */
37
38class BigUnsignedInABase : protected NumberlikeArray<unsigned short> {
39
40public:
41	// The digits of a BigUnsignedInABase are unsigned shorts.
42	typedef unsigned short Digit;
43	// That's also the type of a base.
44	typedef Digit Base;
45
46protected:
47	// The base in which this BigUnsignedInABase is expressed
48	Base base;
49
50	// Creates a BigUnsignedInABase with a capacity; for internal use.
51	BigUnsignedInABase(int, Index c) : NumberlikeArray<Digit>(0, c) {}
52
53	// Decreases len to eliminate any leading zero digits.
54	void zapLeadingZeros() {
55		while (len > 0 && blk[len - 1] == 0)
56			len--;
57	}
58
59public:
60	// Constructs zero in base 2.
61	BigUnsignedInABase() : NumberlikeArray<Digit>(), base(2) {}
62
63	// Copy constructor
64	BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray<Digit>(x), base(x.base) {}
65
66	// Assignment operator
67	void operator =(const BigUnsignedInABase &x) {
68		NumberlikeArray<Digit>::operator =(x);
69		base = x.base;
70	}
71
72	// Constructor that copies from a given array of digits.
73	BigUnsignedInABase(const Digit *d, Index l, Base base);
74
75	// Destructor.  NumberlikeArray does the delete for us.
76	~BigUnsignedInABase() {}
77
78	// LINKS TO BIGUNSIGNED
79	BigUnsignedInABase(const BigUnsigned &x, Base base);
80	operator BigUnsigned() const;
81
82	/* LINKS TO STRINGS
83	 *
84	 * These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to
85	 * represent digits of 0 through 35.  When parsing strings, lowercase is
86	 * also accepted.
87	 *
88	 * All string representations are big-endian (big-place-value digits
89	 * first).  (Computer scientists have adopted zero-based counting; why
90	 * can't they tolerate little-endian numbers?)
91	 *
92	 * No string representation has a ``base indicator'' like ``0x''.
93	 *
94	 * An exception is made for zero: it is converted to ``0'' and not the
95	 * empty string.
96	 *
97	 * If you want different conventions, write your own routines to go
98	 * between BigUnsignedInABase and strings.  It's not hard.
99	 */
100	operator std::string() const;
101	BigUnsignedInABase(const std::string &s, Base base);
102
103public:
104
105	// ACCESSORS
106	Base getBase() const { return base; }
107
108	// Expose these from NumberlikeArray directly.
109	using NumberlikeArray<Digit>::getCapacity;
110	using NumberlikeArray<Digit>::getLength;
111
112	/* Returns the requested digit, or 0 if it is beyond the length (as if
113	 * the number had 0s infinitely to the left). */
114	Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; }
115
116	// The number is zero if and only if the canonical length is zero.
117	bool isZero() const { return NumberlikeArray<Digit>::isEmpty(); }
118
119	/* Equality test.  For the purposes of this test, two BigUnsignedInABase
120	 * values must have the same base to be equal. */
121	bool operator ==(const BigUnsignedInABase &x) const {
122		return base == x.base && NumberlikeArray<Digit>::operator ==(x);
123	}
124	bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); }
125
126};
127
128#endif
129