1 /*
2 * Copyright (c) Oona Räisänen
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 */
17 #ifndef UTIL_H_
18 #define UTIL_H_
19
20 #include <cstdint>
21
22 #include <algorithm>
23 #include <map>
24 #include <numeric>
25 #include <set>
26 #include <string>
27 #include <vector>
28
29 namespace redsea {
30
31 // extract N-bit integer from word, starting at starting_at from the right
32 template<size_t N>
getBits(uint16_t word,size_t starting_at)33 uint16_t getBits(uint16_t word, size_t starting_at) {
34 static_assert(N <= 16, "");
35 return (word >> starting_at) & ((1 << N) - 1);
36 }
37
38 // extract N-bit integer from the concatenation of word1 and word2, starting at
39 // starting_at from the right
40 template<size_t N>
getBits(uint16_t word1,uint16_t word2,size_t starting_at)41 uint32_t getBits(uint16_t word1, uint16_t word2, size_t starting_at) {
42 static_assert(N <= 32, "");
43 return (((word1 << 16) + word2) >> starting_at) & ((1 << N) - 1);
44 }
45
46 std::string getHoursMinutesString(int hour, int minute);
47
48 std::string join(std::vector<std::string> strings, const std::string& d);
49 std::string join(std::vector<uint16_t> nums, const std::string& d);
50
51 std::string getHexString(uint32_t value, int num_nybbles);
52 std::string getPrefixedHexString(uint32_t value, int num_nybbles);
53
54 using CSVRow = std::vector<std::string>;
55
56 class CSVTable {
57 public:
58 std::map<std::string, size_t> titles;
59 std::vector<CSVRow> rows;
60 };
61
62 std::vector<std::vector<std::string>> readCSV(std::vector<std::string> csvdata,
63 char delimiter);
64 std::vector<std::vector<std::string>> readCSV(std::string filename,
65 char delimiter);
66 CSVTable readCSVWithTitles(std::string filename, char delimiter);
67 CSVTable readCSVWithTitles(std::vector<std::string> csvdata,
68 char delimiter);
69
70 class CarrierFrequency {
71 public:
72 enum class Band {
73 LF_MF, FM
74 };
75 public:
76 explicit CarrierFrequency(uint16_t code, Band band = Band::FM);
77 bool isValid() const;
78 int kHz() const;
79 std::string str() const;
80 friend bool operator== (const CarrierFrequency &f1,
81 const CarrierFrequency &f2);
82 friend bool operator< (const CarrierFrequency &f1,
83 const CarrierFrequency &f2);
84
85 private:
86 uint16_t code_;
87 Band band_ { Band::FM };
88 };
89
90 class AltFreqList {
91 public:
92 AltFreqList() = default;
93 void insert(uint16_t af_code);
94 bool isComplete() const;
95 std::set<CarrierFrequency> get() const;
96 void clear();
97
98 private:
99 std::set<CarrierFrequency> alt_freqs_;
100 unsigned num_alt_freqs_ { 0 };
101 bool lf_mf_follows_ { false };
102 };
103
104 template<typename T, size_t N>
105 class RunningSum {
106 public:
RunningSum()107 RunningSum() {
108 std::fill(history_.begin(), history_.end(), 0.f);
109 }
getSum()110 T getSum() const {
111 return std::accumulate(history_.cbegin(), history_.cend(), 0);
112 }
push(int number)113 void push(int number) {
114 history_[pointer_] = number;
115 pointer_ = (pointer_ + 1) % history_.size();
116 }
clear()117 void clear() {
118 std::fill(history_.begin(), history_.end(), 0);
119 }
120
121 private:
122 std::array<T, N> history_;
123 size_t pointer_ { 0 };
124 };
125
126 template<typename T, size_t N>
127 class RunningAverage {
128 public:
RunningAverage()129 RunningAverage() {
130 std::fill(history_.begin(), history_.end(), 0.f);
131 }
push(T value)132 void push(T value) {
133 sum_ -= history_[ptr_];
134 history_[ptr_] = value;
135 sum_ += value;
136 ptr_ = (ptr_ + 1) % history_.size();
137 }
138
getAverage()139 float getAverage() const {
140 return 1.0f * sum_ / history_.size();
141 }
142
143 private:
144 std::array<T, N> history_;
145 T sum_ { 0 };
146 size_t ptr_ { 0 };
147 };
148
149 std::string rtrim(std::string s);
150
151 std::string get_string(const CSVTable& table, const CSVRow& row, const std::string& title);
152 int get_int(const CSVTable& table, const CSVRow& row, const std::string& title);
153 uint16_t get_uint16(const CSVTable& table, const CSVRow& row, const std::string& title);
154 bool row_contains(const CSVTable& table, const CSVRow& row, const std::string& title);
155
156 } // namespace redsea
157 #endif // UTIL_H_
158