-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathStringConverterBase.h
More file actions
143 lines (116 loc) · 4.56 KB
/
StringConverterBase.h
File metadata and controls
143 lines (116 loc) · 4.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#pragma once
#ifndef STRINGCONVERTERBASE_H
#define STRINGCONVERTERBASE_H
// data types
typedef unsigned long long UInt64;
typedef unsigned int UInt32;
#include "IStringConverter.h"
#include "Pow2StringConverter.h"
#include "../Utils/Constants.h"
#include "Bits.h"
#include <string>
#include <vector>
#include <math.h>
using namespace std;
// Base class for ToString converters.
// Contains default implementations of convert operation over <see cref="IntX" /> instances.
class StringConverterBase : public IStringConverter
{
#pragma region Private fields
private:
IStringConverter *_pow2StringConverter; // converter for pow2 case
#pragma endregion Private fields
#pragma region Constructor
public:
// Creates new <see cref="StringConverterBase" /> instance.
// <param name="pow2StringConverter">Converter for pow2 case.</param>
StringConverterBase(IStringConverter &pow2StringConverter)
{
_pow2StringConverter = &pow2StringConverter;
} // end cctor
#pragma endregion Constructor
public:
/// <summary>
/// Returns string representation of <see cref="IntX" /> object in given base.
/// </summary>
/// <param name="intX">Big integer to convert.</param>
/// <param name="numberBase">Base of system in which to do output.</param>
/// <param name="alphabet">Alphabet which contains chars used to represent big integer, char position is coresponding digit value.</param>
/// <returns>Object string representation.</returns>
/// <exception cref="ArgumentException"><paramref name="numberBase" /> is less then 2 or <paramref name="intX" /> is too big to fit in string.</exception>
virtual string ToString(const IntX &intX, const UInt32 numberBase, const string &alphabet)
{
// Test base
if (numberBase < 2 || numberBase > 65536)
{
throw ArgumentException(string(Strings::ToStringSmallBase) + "numberBase");
} // end if
// Special processing for zero values
if (intX.length == 0) return "0";
// Calculate output array length
UInt32 outputLength = (UInt32)ceil(Constants::DigitBaseLog / log(numberBase) * intX.length);
// Define length coefficient for string builder
bool isBigBase = numberBase > alphabet.length();
UInt32 lengthCoef = isBigBase ? (UInt32)ceil(log10(numberBase)) + 2U : 1U;
// Determine maximal possible length of string
UInt64 maxBuilderLength = (UInt64)outputLength * lengthCoef + 1UL;
if (maxBuilderLength > Constants::MaxIntValue)
{
// This big integer can't be transformed to string
throw ArgumentException(string(Strings::IntegerTooBig) + "intX");
} // end if
// Transform digits into another base
vector<UInt32> outputArray = ToString(intX.digits, intX.length, numberBase, outputLength);
// Output everything to the string builder
string outputBuilder;
outputBuilder.resize((int)(outputLength * lengthCoef + 1));
UInt32 Idx = 0; // holds index in string
UInt32 aCount = 0; // counts numbers of char in string
// Maybe append minus sign
if (intX.negative)
{
outputBuilder[Idx] += Constants::DigitsMinusChar;
++Idx;
++aCount;
} // end if
// Output all digits
for (UInt32 i = outputLength - 1; i < outputLength; --i)
{
if (!isBigBase)
{
// Output char-by-char for bases up to covered by alphabet
outputBuilder[Idx] += (alphabet[(int)outputArray[i]]);
++aCount;
} // end if
else
{
// Output digits in bracets for bigger bases
outputBuilder[Idx] += Constants::DigitOpeningBracet;
++Idx;
outputBuilder[Idx] += (char)(outputArray[i] + '0');
++Idx;
outputBuilder[Idx] += Constants::DigitClosingBracet;
aCount += 3;
} // end else
++Idx;
} // end for
outputBuilder.resize(aCount); // resize to correct size
return outputBuilder;
} // end function ToString
/// <summary>
/// Converts digits from internal representaion into given base.
/// </summary>
/// <param name="digits">Big integer digits.</param>
/// <param name="length">Big integer length.</param>
/// <param name="numberBase">Base to use for output.</param>
/// <param name="outputLength">Calculated output length (will be corrected inside).</param>
/// <returns>Conversion result (later will be transformed to string).</returns>
virtual vector<UInt32> ToString(const vector<UInt32> &digits, const UInt32 length, const UInt32 numberBase, UInt32 &outputLength)
{
// Default implementation - always call pow2 converter if numberBase is pow of 2
return numberBase == 1U << Bits::Msb(numberBase)
? _pow2StringConverter->ToString(digits, length, numberBase, outputLength)
: vector<UInt32>();
} // end function ToString
}; // end class StringConverterBase
#endif // !STRINGCONVERTERBASE_H