summaryrefslogtreecommitdiff
path: root/src/core/common/Number.hpp
blob: 5417c2825dd3ac98eabcd491d2183be530f0a6ef (plain)
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
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
    Ousía
    Copyright (C) 2014, 2015  Benjamin Paaßen, Andreas Stöckel

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file Number.hpp
 *
 * Contains the Number class responsible for parsing integers and doubles of
 * various bases.
 *
 * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
 */

#include <cstdint>
#include <string>
#include <unordered_set>

namespace ousia {

// Forward declarations
class CharReader;
class Logger;

/* Class Number */

/**
 * Class used internally to represent a number (integer or double). The number
 * is represented by its components (base value a, nominator n, denominator d,
 * exponent e, sign s and exponent sign sE).
 */
class Number {
private:
	/**
	 * Represents the part of the number: Base value a, nominator n, exponent e.
	 */
	enum class Part { A, N, E };

	/**
	 * Sign of the number and the exponent.
	 */
	int8_t s, sE;

	/**
	 * Exponent.
	 */
	int16_t e;

	/**
	 * Base value, nominator, denominator
	 */
	int64_t a, n, d;

	/**
	 * Variable specifying whether the parsed number actually was an integer.
	 */
	bool validInteger;

	/**
	 * Appends the value of the character c to the internal number
	 * representation and reports any errors that might occur.
	 *
	 * @param c is the character that should be appended.
	 * @param base is the current base.
	 * @param p is the current number part.
	 * @param reader is the char reader which points at the current reading
	 * position.
	 */
	bool appendChar(char c, int base, Part p, CharReader &reader,
	                Logger &logger);

public:
	/**
	 * Constructor of the number class.
	 */
	Number() : s(1), sE(1), e(0), a(0), n(0), d(1), validInteger(true) {}

	/**
	 * Returns the represented double value.
	 *
	 * @return the double value the number is currently representing.
	 */
	double doubleValue();

	/**
	 * Returns the represented integer value. Only a lossless operation, if the
	 * number is an integer (as can be checked via the isInt method), otherwise
	 * the exponent and the fractional value will be truncated.
	 *
	 * @return the integer value (ignoring any exponent)
	 */
	int64_t intValue();

	/**
	 * Returns true, if the number was a valid integer.
	 *
	 * @return true if the number is an integer, false otherwise.
	 */
	bool isInt() { return validInteger; }

	/**
	 * Tries to parse the number from the given stream and loggs any errors to
	 * the given logger instance. Numbers are terminated by one of the given
	 * delimiters.
	 *
	 * @param reader is the char reader from which the number should be read.
	 * @param logger is the logger instance to which error messages should be
	 * written.
	 * @param delims is a set of characters at which parsing should stop. The
	 * reader is positioned at the delimiter.
	 * @return true if parsing was successful, false otherwise.
	 */
	bool parse(
	    CharReader &reader, Logger &logger,
	    const std::unordered_set<char> &delims = std::unordered_set<char>{});

	/**
	 * Tries to parse the number from the given string and loggs any errors to
	 * the given logger instance.
	 *
	 * @param str is the string from which the number should be read.
	 * @param logger is the logger instance to which error messages should be
	 * written.
	 * @return true if parsing was successful, false otherwise.
	 */
	bool parse(const std::string &str, Logger &logger);

	/**
	 * Parses an integer with a fixed length and the given base.
	 *
	 * @param reader is a reference at the char reader from which the number
	 * should be read.
	 * @param len is the length of the integer sequence.
	 * @param base is the base of the number.
	 * @param logger is the logger instance to which error messages should be
	 * written.
	 * @return true if parsing was successful, false otherwise.
	 */
	bool parseFixedLengthInteger(CharReader &reader, int len, int base,
	                      Logger &logger);
};
}