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
157
|
/*
* Copyright (c) 2020-2021 Vasile Vilvoiu <vasi@vilvoiu.ro>
*
* specgram is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef _INPUT_PARSER_HPP_
#define _INPUT_PARSER_HPP_
#include <vector>
#include <complex>
#include <memory>
/**
* Input data type
*/
enum class DataType {
/* signed integer */
kSignedInt8,
kSignedInt16,
kSignedInt32,
kSignedInt64,
/* unsigned integer */
kUnsignedInt8,
kUnsignedInt16,
kUnsignedInt32,
kUnsignedInt64,
/* floating point */
kFloat32,
kFloat64
};
/* Complex type that we normalize everything to */
typedef std::complex<double> Complex;
/* Window of real numbers */
typedef std::vector<double> RealWindow;
/* Window of complex numbers */
typedef std::vector<Complex> ComplexWindow;
/**
* Input parser base class
*/
class InputParser {
protected:
double prescale_factor_; /* factor that is applied before further processing */
bool is_complex_; /* input is complex? */
std::vector<Complex> values_; /* parsed values */
InputParser() = delete;
/**
* @param prescale Prescale factor, applied after parsing.
* @param is_complex If true, input is treated as complex-typed. Two input
* values will be read for each output value.
*/
explicit InputParser(double prescale, bool is_complex);
public:
InputParser(const InputParser &c) = delete;
InputParser(InputParser &&) = delete;
InputParser & operator=(const InputParser&) = delete;
virtual ~InputParser() = default;
/**
* Factory method for retrieving a suitable parser.
* @param dtype Input data type.
* @param prescale Prescale factor to apply after parsing.
* @param is_complex If true, input is treated as complex-typed. Two input
* values will be read for each output value.
* @return New Parser object.
*/
static std::unique_ptr<InputParser> Build(DataType dtype, double prescale, bool is_complex);
/**
* @return The number of values that have been parsed, but not yet retrieved.
*/
std::size_t GetBufferedValueCount() const;
/**
* Retrieves, without removing, from the parsed (buffered) value array.
* @param count Number of values to retrieve.
* @return
*/
std::vector<Complex> PeekValues(std::size_t count) const;
/**
* Removes values from the parsed (buffered) values array.
* @param count Number of values to remove.
*/
void RemoveValues(std::size_t count);
/**
* Parses a block of bytes.
* @param block Block of bytes that must have a size that is a multiple of
* the underlying data type size (or twice that for complex).
* @return Number of parsed values.
*/
virtual std::size_t ParseBlock(const std::vector<char> &block) = 0;
/**
* @return Size of the underlying data type (or twice for complex).
*/
virtual std::size_t GetDataTypeSize() const = 0;
/**
* @return True if underlying data type is signed.
*/
virtual bool IsSigned() const = 0;
/**
* @return True if underlying data type is floating point.
*/
virtual bool IsFloatingPoint() const = 0;
/**
* @return True if parsing complex input.
*/
virtual bool IsComplex() const { return is_complex_; };
};
/**
* Specialized parser for integer input.
*/
template <class T>
class IntegerInputParser : public InputParser {
public:
IntegerInputParser() = delete;
explicit IntegerInputParser(double prescale, bool is_complex);
std::size_t ParseBlock(const std::vector<char> &block) override;
std::size_t GetDataTypeSize() const override;
bool IsSigned() const override { return std::numeric_limits<T>::is_signed; };
bool IsFloatingPoint() const override { return false; };
};
/**
* Specialized parser for floating point input.
*/
template <class T>
class FloatInputParser : public InputParser {
public:
FloatInputParser() = delete;
explicit FloatInputParser(double prescale, bool is_complex);
std::size_t ParseBlock(const std::vector<char> &block) override;
std::size_t GetDataTypeSize() const override;
bool IsSigned() const override { return true; };
bool IsFloatingPoint() const override { return true; };
};
#endif
|