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