diff --git a/src/Error.h b/src/Error.h index 195c7a4..7581743 100644 --- a/src/Error.h +++ b/src/Error.h @@ -237,6 +237,11 @@ namespace ts { details_ptr->extra_properties["extra_msg"] = message; } + command_result(error::type error, const std::map& properties) : command_result{error, ""} { + assert(this->is_detailed()); + this->details()->extra_properties = properties; + } + #ifndef _NDEBUG /* if we're not using any debug we dont have to use a deconstructor. A deconstructor prevent a direct uint64_t return as described above */ ~command_result() { @@ -259,7 +264,6 @@ namespace ts { ErrorType(const uint16_t errorId, const std::string &name, const std::string &message) : errorId(errorId), name(name), message(message) {} ErrorType(const ErrorType& ref) : errorId(ref.errorId), name(ref.name), message(ref.message) {} - ErrorType(ErrorType& ref) : errorId(ref.errorId), name(ref.name), message(ref.message) {} ErrorType(ErrorType&& ref) : errorId(ref.errorId), name(std::move(ref.name)), message(std::move(ref.message)) {} uint16_t errorId; diff --git a/src/License.h b/src/License.h index 19c273a..b676407 100644 --- a/src/License.h +++ b/src/License.h @@ -53,7 +53,7 @@ namespace license { struct LicenseKey { bool privateKey = false; uint8_t privateKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t publicKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t publicKeyData[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; }; typedef uint8_t LicensePublicKey[32]; diff --git a/src/Properties.h b/src/Properties.h index 6b2298f..df8b78c 100644 --- a/src/Properties.h +++ b/src/Properties.h @@ -53,23 +53,23 @@ namespace ts { typedef uint32_t flag_type; enum flag : flag_type { FLAG_BEGIN = 0b1, - FLAG_INTERNAL = FLAG_BEGIN << 1, //Just for internal usage - FLAG_GLOBAL = FLAG_INTERNAL << 1, //Not server bound - FLAG_SNAPSHOT = FLAG_GLOBAL << 1, //Saved within snapshots - FLAG_SAVE = FLAG_SNAPSHOT << 1, //Saved to database - FLAG_SAVE_MUSIC = FLAG_SAVE << 1, //Saved to database - FLAG_NEW = FLAG_SAVE_MUSIC << 1, //Its a non TeamSpeak property - FLAG_SERVER_VARIABLE = FLAG_NEW << 1, - FLAG_SERVER_VIEW = FLAG_SERVER_VARIABLE << 1, - FLAG_CLIENT_VARIABLE = FLAG_SERVER_VIEW << 1, - FLAG_CLIENT_VIEW = FLAG_CLIENT_VARIABLE << 1, - FLAG_CLIENT_INFO = FLAG_CLIENT_VIEW << 1, - FLAG_CHANNEL_VARIABLE = FLAG_CLIENT_INFO << 1, - FLAG_CHANNEL_VIEW = FLAG_CHANNEL_VARIABLE << 1, - FLAG_GROUP_VIEW = FLAG_CHANNEL_VIEW << 1, - FLAG_INSTANCE_VARIABLE = FLAG_GROUP_VIEW << 1, - FLAG_USER_EDITABLE = FLAG_INSTANCE_VARIABLE << 1, - FLAG_PLAYLIST_VARIABLE = FLAG_USER_EDITABLE << 1, + FLAG_INTERNAL = FLAG_BEGIN << 1UL, //Just for internal usage + FLAG_GLOBAL = FLAG_INTERNAL << 1UL, //Not server bound + FLAG_SNAPSHOT = FLAG_GLOBAL << 1UL, //Saved within snapshots + FLAG_SAVE = FLAG_SNAPSHOT << 1UL, //Saved to database + FLAG_SAVE_MUSIC = FLAG_SAVE << 1UL, //Saved to database + FLAG_NEW = FLAG_SAVE_MUSIC << 1UL, //Its a non TeamSpeak property + FLAG_SERVER_VARIABLE = FLAG_NEW << 1UL, + FLAG_SERVER_VIEW = FLAG_SERVER_VARIABLE << 1UL, + FLAG_CLIENT_VARIABLE = FLAG_SERVER_VIEW << 1UL, + FLAG_CLIENT_VIEW = FLAG_CLIENT_VARIABLE << 1UL, + FLAG_CLIENT_INFO = FLAG_CLIENT_VIEW << 1UL, + FLAG_CHANNEL_VARIABLE = FLAG_CLIENT_INFO << 1UL, + FLAG_CHANNEL_VIEW = FLAG_CHANNEL_VARIABLE << 1UL, + FLAG_GROUP_VIEW = FLAG_CHANNEL_VIEW << 1UL, + FLAG_INSTANCE_VARIABLE = FLAG_GROUP_VIEW << 1UL, + FLAG_USER_EDITABLE = FLAG_INSTANCE_VARIABLE << 1UL, + FLAG_PLAYLIST_VARIABLE = FLAG_USER_EDITABLE << 1UL, }; static constexpr const char *flag_names[sizeof(flag) * 8] = {"UNDEFINED", "FLAG_INTERNAL", "FLAG_GLOBAL", "FLAG_SNAPSHOT", "FLAG_SAVE", "FLAG_SAVE_MUSIC", "FLAG_NEW", @@ -773,12 +773,8 @@ namespace ts { Properties(const Properties&) = delete; Properties(Properties&&) = delete; - std::vector list_properties(property::flag_type flagMask = ~0, property::flag_type negatedFlagMask = 0); + std::vector list_properties(property::flag_type flagMask = (property::flag_type) ~0UL, property::flag_type negatedFlagMask = 0); std::vector all_properties(); - /* - std::deque> listProperties(property::flag_type flagMask = ~0, property::flag_type negatedFlagMask = 0); - std::deque> allProperties(); - */ template bool register_property_type() { @@ -786,25 +782,6 @@ namespace ts { return this->register_property_type(type, property::impl::length(type), property::impl::offset(type)); } - /* - template - std::shared_ptr registerProperty(PT property){ - auto info = property::impl::info(property); - { - threads::MutexLock lock(this->propsLock); - for(const auto& elm : this->properties) { - if(*info == elm->type()){ - std::cerr << "Double registration of " << elm->type().name << "\n"; - return this->find(property::impl::type(), property); - } - } - - properties.push_back(std::make_shared(this, info)); - } - return this->find(property::impl::type(), property); - } - */ - template bool hasProperty(T type) { return this->has(property::impl::type(), type); } @@ -846,11 +823,9 @@ namespace ts { bool save = true; std::vector> notifyFunctions{}; - std::recursive_mutex propsLock{}; - //std::deque> properties{}; size_t properties_count = 0; - std::deque> properties; + std::vector> properties; }; }; diff --git a/src/query/command2.cpp b/src/query/command2.cpp index c1e8aba..ac1fe1e 100644 --- a/src/query/command2.cpp +++ b/src/query/command2.cpp @@ -42,7 +42,7 @@ CONVERTER_ST(const_char__ , return str.c_str();, return std::string(std::any_cas command::command(const std::string& command, bool editable) { this->handle = make_shared(); - this->handle->editiable = editable; + this->handle->editable = editable; this->handle->command = command; } @@ -56,7 +56,7 @@ void command::set_identifier(const std::string &command) { command_bulk command::bulk(size_t index) { if(this->handle->bulks.size() <= index) { - if(!this->handle->editiable) + if(!this->handle->editable) throw command_bulk_exceed_index_exception(); while(this->handle->bulks.size() <= index) { @@ -229,7 +229,7 @@ command_entry command_bulk::value(const std::string &key) { auto& values = this->handle->values; auto index = values.find(key); if(index == values.end()) { - if(!this->handle->handle->editiable) + if(!this->handle->handle->editable) throw command_value_missing_exception(this->bulk_index, key); auto result = make_shared(); diff --git a/src/query/command2.h b/src/query/command2.h index 7a9cb27..f754103 100644 --- a/src/query/command2.h +++ b/src/query/command2.h @@ -38,7 +38,7 @@ namespace ts { struct command_data { std::string command; - bool editiable; + bool editable; std::deque> bulks; std::deque triggers; }; @@ -136,7 +136,7 @@ namespace ts { return this->string(); } - template ::value && !std::is_same::value, int> = 0> + template ::value, int> = 0> T as() { static_assert(converter::supported, "Target type isn't supported!"); static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); @@ -308,13 +308,20 @@ namespace ts { }; using default_options = options; - struct base { }; + struct base { + virtual ~base() = default; + }; struct base_data { int type; /* 1 = field | 2 = switch | 3 = command handle */ option_data options; }; + struct field_base : public base { + virtual std::vector& ref_values() = 0; + virtual const std::vector& ref_values() const = 0; + }; + struct field_data : public base_data { const char* key; const std::type_info& field_type; @@ -323,19 +330,12 @@ namespace ts { void* to_string; }; - struct field_base { - typedef std::vector&(*ref_values_fn)(); - static inline std::vector& ref_values(const void* _this) { - void** vtable = *(void***) _this; - return ((ref_values_fn) vtable[0])(); - } - }; - template - struct field : public base, public options, public extends... { + struct field : public field_base, public options, public extends... { friend struct command_parser>; static_assert(converter::supported, "Target type isn't supported!"); static_assert(!converter::supported || converter::from_string, "Target type dosn't support parsing"); + static_assert(impl::templates::_or_::value...>::value == false, "Extensions could not have data members"); protected: using object_t = field_data; @@ -344,7 +344,6 @@ namespace ts { static constexpr auto from_string = converter::from_string; public: - template ::value...>::value, int> = 0 */> using as_optional = field, optional_extend, extends...>; @@ -391,27 +390,32 @@ namespace ts { return this->as(); } + std::vector& ref_values() final { return this->values; } + const std::vector& ref_values() const final { return this->values; } protected: - /* ATTENTION: This must be placed at index 0 within the VTable */ - virtual __attribute__used std::vector& _v_ref_values() { - return this->values; - } - std::vector values; }; struct optional_extend { public: inline bool has_value() const { - auto& values = field_base::ref_values(this); + auto base = dynamic_cast((struct base*) this); + assert(base); + + const auto& values = base->ref_values(); return !values.empty() && !values[0].is_empty(); } template inline T get_or(T&& value = T{}) const { - if(this->has_value()) - return field_base::ref_values(this).front().as(); - return value; + auto base = dynamic_cast((struct base*) this); + assert(base); + + auto& values = base->ref_values(); + if(values.empty() || values[0].is_empty()) + return value; + + return values.front().as(); } }; @@ -421,10 +425,18 @@ namespace ts { return !this->at(index).is_empty(); } - inline size_t length() const { return field_base::ref_values(this).size(); } + inline size_t length() const { + auto base = dynamic_cast((struct base*) this); + assert(base); + + return base->ref_values().size(); + } inline command_entry at(size_t index) const { - auto& values = field_base::ref_values(this); + auto base = dynamic_cast((struct base*) this); + assert(base); + + auto& values = base->ref_values(); if(index > values.size()) throw command_bulk_exceed_index_exception(); @@ -436,16 +448,12 @@ namespace ts { } }; - struct trigger_data : public base_data { - const char* key; + struct trigger_base : public base { + virtual bool& ref_flag() = 0; }; - struct trigger_base : public base { - typedef bool&(*ref_flag_fn)(); - static inline bool& ref_flag(void* _this) { - void** vtable = *(void***) _this; - return ((ref_flag_fn) vtable[0])(); - } + struct trigger_data : public base_data { + const char* key; }; template @@ -468,109 +476,14 @@ namespace ts { inline bool is_set() const { return this->flag_set; } operator bool() const { return this->flag_set; } - private: - /* ATTENTION: This must be placed at index 0 within the VTable */ - virtual __attribute__used bool& _v_ref_values() { + bool& ref_flag() override { return this->flag_set; } - bool flag_set; - }; - - struct command_handle_data : public base_data { }; - - struct command_handle_base : public base { - typedef command&(*ref_flag_fn)(); - static inline command& ref_command(void* _this) { - void** vtable = *(void***) _this; - return ((ref_flag_fn) vtable[0])(); - } - }; - - template - struct command_handle : public command_handle_base, public options { - public: - using object_t = command_handle_data; - inline static std::shared_ptr describe() { - return std::make_shared( - command_handle_data { - 3, - options::options_object() - } - ); - } - - inline command get_command() { return this->_command; } - operator command() { return this->_command; } - - inline command* operator->() const noexcept { - return (command*) &_command; - } - - /* - template - auto operator[](Arg &&arg) -> decltype(get_command()[std::forward(arg)]) { - return _command[std::forward(arg)]; - } - */ - template - decltype(std::declval()[std::forward(Arg{})]) operator[](Arg &&arg) { - return _command[std::forward(arg)]; - } private: - /* ATTENTION: This must be placed at index 0 within the VTable */ - virtual __attribute__used class command& _v_ref_values() { - return this->_command; - } - - command _command; + bool flag_set = false; }; - typedef std::vector> function_descriptors_t; - - template - struct describe { - inline static void apply(function_descriptors_t& result) {} - }; - - template - struct describe { - inline static void apply(function_descriptors_t& result) { - result.push_back(T::describe()); - describe::apply(result); - } - }; - - inline void parse_field(const std::shared_ptr& description, void* field, command& cmd) { - //if(!description->options.optional && !cmd.has_value(description->key)) - // throw command_value_missing_exception(); - - auto& values = field_base::ref_values(field); - values.clear(); - - if(description->options.bulked) { - values.resize(cmd.bulk_count()); - for(size_t bulk_index = 0; bulk_index < cmd.bulk_count(); bulk_index++) { - if(!cmd[bulk_index].has(description->key)) { - if(!description->options.optional) - throw command_value_missing_exception(bulk_index, description->key); - else - values[bulk_index] = command_entry::empty; - } else { - values[bulk_index] = cmd[bulk_index][description->key]; - } - } - } else { - if(!cmd.has_value(description->key)) { - if(!description->options.optional) - throw command_value_missing_exception(0, description->key); - else - values.push_back(command_entry::empty); - } else - values.push_back(cmd[description->key]); - } - } - template struct command_parser> { constexpr static bool supported = true; @@ -586,7 +499,33 @@ namespace ts { assert(descriptor->type == 1); field_t result{}; - parse_field(descriptor, (void*) &result, cmd); + + //if(!description->options.optional && !cmd.has_value(description->key)) + // throw command_value_missing_exception(); + auto& values = result.ref_values(); + values.clear(); + + if(descriptor->options.bulked) { + values.resize(cmd.bulk_count()); + for(size_t bulk_index = 0; bulk_index < cmd.bulk_count(); bulk_index++) { + if(!cmd[bulk_index].has(descriptor->key)) { + if(!descriptor->options.optional) + throw command_value_missing_exception(bulk_index, descriptor->key); + else + values[bulk_index] = command_entry::empty; + } else { + values[bulk_index] = cmd[bulk_index][descriptor->key]; + } + } + } else { + if(!cmd.has_value(descriptor->key)) { + if(!descriptor->options.optional) + throw command_value_missing_exception(0, descriptor->key); + else + values.push_back(command_entry::empty); + } else + values.push_back(cmd[descriptor->key]); + } return result; } @@ -607,37 +546,32 @@ namespace ts { assert(descriptor->type == 2); trigger_t result{}; - trigger_base::ref_flag(&result) = cmd.has_trigger(descriptor->key); + result.ref_flag() = cmd.has_trigger(descriptor->key); return result; } }; - template - struct command_parser> { + struct command_data : public base_data { }; + + template <> + struct command_parser { constexpr static bool supported = true; - typedef command_handle command_handle_t; - using descriptor_t = std::shared_ptr; + using descriptor_t = std::shared_ptr; - inline static descriptor_t describe() { - return command_handle_t::describe(); - } + inline static descriptor_t describe() { return std::make_shared(command_data{{3, {false, false}}}); } - inline static command_handle_t apply(descriptor_t& descriptor, command& cmd) { + inline static command& apply(descriptor_t& descriptor, command& cmd) { assert(descriptor->type == 3); - - command_handle_t result{}; - command_handle_base::ref_command(&result) = cmd; - return result; + return cmd; } }; template struct command_parser { - constexpr static bool supported = std::is_same::type>::type, command>::value; - static_assert(supported, "This type isn't supported!"); + constexpr static bool supported = false; - using descriptor_t = std::shared_ptr; + using descriptor_t = std::shared_ptr; inline static descriptor_t describe() { return nullptr; @@ -649,9 +583,6 @@ namespace ts { }; } - /* direct use of command is possible as well! */ - using command_handle = impl::command_handle; - template using field = impl::field; @@ -659,16 +590,13 @@ namespace ts { using trigger = impl::trigger; template - inline impl::function_descriptors_t describe_function() { - impl::function_descriptors_t result; - impl::describe::apply(result); - return result; + inline std::array, sizeof...(args_t)> describe_function(void(*)(args_t...)) { + static_assert(!impl::templates::_or_::type>::supported...>::value, "Not any function argument type is supported"); + return {impl::command_parser::type>::describe()...}; } struct invocable_function { - void operator()(command& command) { - this->invoke(command); - } + void operator()(command& command) { this->invoke(command); } virtual void invoke(command& command) = 0; }; @@ -684,7 +612,7 @@ namespace ts { void(*function)(args_t...); void invoke(command& command) override { - function(command_parser_t::apply(std::get::value>(descriptors), command)...); + this->function(command_parser_t::apply(std::get::value>(descriptors), command)...); } }; diff --git a/test/CommandTest.cpp b/test/CommandTest.cpp index 4875440..7672037 100644 --- a/test/CommandTest.cpp +++ b/test/CommandTest.cpp @@ -23,11 +23,11 @@ using trigger = ts::descriptor::trigger; void handleCommand( ts::command& _cmd, - cconstants::return_code::optional return_code, - field key_a, - field::optional key_b, - field::optional::bulked key_c, - trigger switch_test + const cconstants::return_code::optional& return_code, + const field& key_a, + const field::optional& key_b, + const field::optional::bulked& key_c, + const trigger& switch_test ) { if(key_a.value() < 10) cout << "ERROR" << endl; @@ -67,18 +67,6 @@ void eval_test(command_result x) { int main() { //for(const auto& error : avariableErrors) // cout << error.name << " = " << hex << "0x" << error.errorId << "," << endl; - #if false - { - string error; - istringstream is(base64::decode("AQCvbHFTQDY/terPeilrp/ECU9xCH5U3xC92lYTNaY/0KQAJFueAazbsgAAAACVUZWFtU3BlYWsgU3lzdGVtcyBHbWJIAADCxw83PomiAdX11jLso/hdMVov4e8N79iq2NRhwkIjqgAKSyfbMFu6mwAAACRUZWFtU3BlYWsgc3lzdGVtcyBHbWJIAAA+kiuhufX/V96lZzq4MICxnYxFPkV/mG03Pu+VYgUISwIKU0+AC1RkAAQAAAIASmFuLU5pa2xhcyBLZXR0ZW5idXJnAADlcwyCViOfHJKYvWHHqyL9R1Ba5ZP+cL7MQ5nI7s1R2yAKnICdCp0pXQ==")); - auto chain = LicenseChain::parse(is, error); - chain->print(); - cout << base64::encode(chain->generatePublicKey(public_root)) << endl; - cout << base64::encode(chain->generatePublicKey(public_root, 1)) << endl; - cout << base64::encode(chain->generatePublicKey(public_root, 2)) << endl; - cout << base64::encode(chain->generatePublicKey(public_root, 3)) << endl; - } - #endif eval_test(test()); eval_test(test2()); @@ -127,7 +115,7 @@ int main() { cout << ts::command::parse("a=c", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; cout << ts::command::parse("a=c | a=c -x", false).build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; cout << ts::command::parse("a a=c|a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; - cout << ts::command::parse("a a=c a=c2 -z | a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; + cout << ts::command::parse("a a=c a=c2 -z | -? a=c").build(ts::command::format::BRACE_ESCAPED_QUERY) << endl; /* * @@ -147,6 +135,8 @@ int main() { cmd[1]["key_c"] = "key_c_value_1"; cmd.set_trigger("test"); + auto result = ts::descriptor::describe_function(handleCommand); + auto cmd_handler = ts::descriptor::parse_function(handleCommand); cmd_handler->invoke(cmd); cout << cmd.build() << endl;