#pragma once #include #include #include #include #include #include #include namespace trygvis { namespace sensor { //using namespace std; template using o = std::optional; enum class sample_format_type { AUTO, CSV, KEY_VALUE, JSON, SQL, RRD, }; std::string to_string(const sample_format_type &arg); std::ostream& operator<<(std::ostream& os, sample_format_type const& type); std::istream& operator>>(std::istream& is, sample_format_type& type); enum class time_resolution { SECONDS, MILLISECONDS, }; std::ostream& operator<<(std::ostream& os, time_resolution const& type); std::istream& operator>>(std::istream& is, time_resolution & type); class sample_exception : public std::runtime_error { public: sample_exception(const std::string &what) : runtime_error(what) { } }; class KeyDictionary; class SampleKey; class KeyDictionary; using SampleKeyVector = std::vector; using SampleKeyIndex = SampleKeyVector::size_type; struct SampleKey { private: SampleKey(const SampleKey& that) = delete; SampleKey(SampleKeyIndex index, const std::string &name) : index(index), name(name) { if (name.length() == 0) { throw sample_exception("Bad sample key."); } } public: friend class KeyDictionary; inline bool operator==(const SampleKey &that) const { return name == that.name; } const SampleKeyIndex index; const std::string name; }; class KeyDictionary { public: KeyDictionary() { } ~KeyDictionary() { std::for_each(keys.begin(), keys.end(), std::default_delete()); } KeyDictionary(KeyDictionary& that) = delete; KeyDictionary& operator=(const KeyDictionary&) = delete; const SampleKey *indexOf(const std::string &key) { SampleKeyIndex i = 0; for (auto ptr = keys.cbegin(); ptr != keys.cend(); ptr++, i++) { if ((*ptr)->name == key) { return *ptr; } } i = keys.size(); auto sample_key = new SampleKey(i, key); keys.push_back(sample_key); return sample_key; } SampleKey *at(SampleKeyIndex i) const { if (i >= keys.size()) { throw sample_exception("Out of bounds"); } return keys.at(i); } std::vector findIndexes(SampleKeyVector &keys) { std::vector indexes; for (auto &key: keys) { auto index = indexOf(key->name); indexes.push_back(index); } return indexes; } inline SampleKeyVector::const_iterator end() const { return keys.cend(); } inline SampleKeyVector::const_iterator begin() const { return keys.cbegin(); } // string nameOf(SampleKeyIndex index) { // return keys.at(index).name; // } inline SampleKeyVector::size_type size() const { return keys.size(); } inline bool empty() const { return keys.empty(); } private: SampleKeyVector keys; }; class SampleRecord { public: typedef std::vector> vec; SampleRecord(KeyDictionary &dict) : dict(dict) { } SampleRecord(KeyDictionary &dict, vec values) : dict(dict), values(values) { } SampleRecord(const SampleRecord ©) : dict(copy.dict), values(copy.values) { } inline vec::const_iterator cbegin() const { return values.cbegin(); } inline vec::const_iterator cend() const { return values.cend(); } inline bool empty() const { return values.empty(); } const o at(const SampleKey *key) const { SampleKeyIndex index = key->index; if (index >= values.size()) { return o(); } return values.at(index); } SampleRecord& set(const SampleKey *key, const std::string &value) { values.resize(std::max(values.size(), key->index + 1)); values.at(key->index) = value; return *this; } template const o lexical_at(const SampleKey *key) const; std::string to_string() const { SampleKeyIndex i = 0; std::string s; for (auto ptr = values.begin(); ptr != values.end(); ptr++, i++) { auto o = *ptr; if (!o) { continue; } auto value = *o; s += dict.at(i)->name + " = " + value + ", "; } return s; } KeyDictionary &dict; private: vec values; }; } }