#pragma once #ifdef byte #define byte asdd #ifndef WIN32 #warning The byte macro is already defined! Undefining it! #endif #undef byte #endif #include #include #include #include #include #include #include #include "../Variable.h" #ifdef HAVE_JSON #include #endif namespace ts { #define PARM_TYPE(type, fromString, toString) \ BaseCommandParm(std::string key, type value) : BaseCommandParm(std::pair(key, "")) {\ toString; \ } \ BaseCommandParm& operator=(type value){ \ toString; \ return *this; \ } \ \ operator type(){ \ fromString; \ } class Command; class ValueList; //PARM_TYPE(ts::Property, return ts::Property(nullptr, key(), value(), 0), f_value() = value.value()); class ParameterBulk { friend class Command; friend class ValueList; public: ParameterBulk(const ParameterBulk& ref) : parms(ref.parms) {} variable operator[](size_t index){ if(parms.size() > index) return parms[index]; return variable{"", "", VARTYPE_NULL}; } const variable& operator[](const std::string& key) const { for(const auto& elm : parms) if(elm.key() == key){ return elm; } throw std::invalid_argument("could not find key [" + key + "]"); } variable& operator[](const std::string& key) { for(auto& elm : parms) if(elm.key() == key){ return elm; } this->parms.push_back(variable(key, "", VariableType::VARTYPE_NULL)); return this->operator[](key); } bool has(const std::string& key) const { for(const auto& elm : parms) if(elm.key() == key && elm.type() != VariableType::VARTYPE_NULL) return true; return false; } std::deque keys() const { std::deque result; for(const auto& elm : parms) result.push_back(elm.key()); return result; } ParameterBulk& operator=(const ParameterBulk& ref){ parms = ref.parms; return *this; } private: ParameterBulk() {} ParameterBulk(std::deque p) : parms(p) {} std::deque parms; }; class ValueList { friend class Command; public: ValueList() = delete; ValueList(const ValueList& ref) : key(ref.key), bulkList(ref.bulkList) {} variable operator[](int index){ while(index >= bulkList.size()) bulkList.push_back(ParameterBulk()); return bulkList[index][key]; } variable first() const { int index = 0; while(index < bulkList.size() && !bulkList[index].has(key)) index++; if(index < bulkList.size()) return bulkList[index][key]; return variable{this->key, "", VariableType::VARTYPE_NULL}; throw std::invalid_argument("could not find key [" + key + "]"); } size_t size(){ size_t count = 0; for(const auto& blk : this->bulkList) if(blk.has(this->key)) count++; return count; } template ValueList& operator=(T var){ operator[](0) = var; return *this; } ValueList& operator=(ts::ValueList& var){ operator[](0) = var.first().value(); return *this; } template T as() const { return first().as(); } template operator T() { return as(); } template bool operator==(T other){ return as() == other; } template bool operator!=(T other){ return as() != other; } std::string string() const { return as(); } friend std::ostream& operator<<(std::ostream&, const ValueList&); private: ValueList(std::string& key, std::deque& bulkList) : key(key), bulkList(bulkList) {} std::string key; public: std::deque& bulkList; }; inline std::ostream& operator<<(std::ostream& stream,const ValueList& list) { stream << "{ Key: " << list.key << " = ["; for(auto it = list.bulkList.begin(); it != list.bulkList.end(); it++) if(it->has(list.key)) { stream << (*it)[list.key].value(); if(it + 1 != list.bulkList.end()) stream << ", "; } stream << "]}"; return stream; } class Command { public: static Command parse(const pipes::buffer_view& buffer, bool expect_command = true, bool drop_non_utf8 = false); explicit Command(const std::string& command); explicit Command(const std::string& command, std::initializer_list); explicit Command(const std::string& command, std::initializer_list>); Command(const Command&); ~Command(); inline std::string command() const { return getCommand(); } std::string getCommand() const { return _command; } std::string build(bool escaped = true) const; #ifdef HAVE_JSON Json::Value buildJson() const; #endif const ParameterBulk& operator[](int index) const { if(bulks.size() <= index) throw std::invalid_argument("got out of length"); return bulks[index]; } ParameterBulk& operator[](int index){ while(bulks.size() <= index) bulks.push_back(ParameterBulk{}); return bulks[index]; } ValueList operator[](std::string key){ return ValueList(key, bulks); } size_t bulkCount() const { return bulks.size(); } void pop_bulk(); void push_bulk_front(); bool hasParm(std::string); std::deque parms(); void enableParm(const std::string& key){ toggleParm(key, true); } void disableParm(const std::string& key){ toggleParm(key, false); } void toggleParm(const std::string& key, bool flag); void reverseBulks(); private: Command(); std::string _command; std::deque bulks; std::deque paramethers; }; } DEFINE_VARIABLE_TRANSFORM_TO_STR(ts::ValueList, in.string()); DEFINE_VARIABLE_TRANSFORM_TYPE(ts::ValueList, VARTYPE_TEXT); #undef PARM_TYPE