#pragma once #include #include #include #include #include namespace trygvis { namespace sensor { using namespace std; template using o = boost::optional; enum class sample_format_type { AUTO, CSV, KEY_VALUE, JSON, SQL, RRD, }; 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 runtime_error { public: sample_exception(const string &what) : runtime_error(what) { } }; class KeyDictionary; class SampleKey; class KeyDictionary; using SampleKeyVector = vector; using SampleKeyIndex = SampleKeyVector::size_type; struct SampleKey { private: SampleKey(const SampleKey& that) = delete; SampleKey(SampleKeyIndex index, const 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 string name; }; class KeyDictionary { public: KeyDictionary() { } ~KeyDictionary() { std::for_each(keys.begin(), keys.end(), std::default_delete()); } KeyDictionary(KeyDictionary& that) = delete; SampleKey *indexOf(const 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); } vector findIndexes(SampleKeyVector &keys) { 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 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(max(values.size(), key->index + 1)); values.at(key->index).reset(value); return *this; } template const o lexical_at(const SampleKey *key) const; string to_string() const { SampleKeyIndex i = 0; string s; for (auto ptr = values.begin(); ptr != values.end(); ptr++, i++) { auto o = *ptr; if (!o) { continue; } auto value = o.get(); s += dict.at(i)->name + " = " + value + ", "; } return s; } KeyDictionary &dict; private: vec values; }; } }