/* Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ABSTRACT_OPTION_INCLUDED #define ABSTRACT_OPTION_INCLUDED #include #include #include "my_getopt.h" #include "i_option_changed_listener.h" #include "i_callable.h" namespace Mysql{ namespace Tools{ namespace Base{ namespace Options{ class Abstract_options_provider; /** Abstract base with common option functionalities. */ template class Abstract_option : public I_option { public: virtual ~Abstract_option(); /** Adds new callback for this option for option_parsed() event to callback chain. I_Callable can be replaced with std::Function once we get one. */ T_type* add_callback(Mysql::I_callable* callback); /** Sets optid to given character to make possible usage of short option alternative. */ T_type* set_short_character(char code); protected: /** Constructs new option. @param value Pointer to object to receive option value. @param var_type my_getopt internal option type. @param name Name of option. It is used in command line option name as --name. @param desription Description of option to be printed in --help. @param default_value default value to be supplied to internal option data structure. */ Abstract_option(void* value, ulong var_type, std::string name, std::string description, uint64 default_value); /** Returns my_getopt internal option data structure representing this option. To be used by Abstract_options_provider when preparing options array to return. */ my_option get_my_option(); /** Method to set listener on option changed events. For use from Abstract_options_provider class only. */ void set_option_changed_listener(I_option_changed_listener* listener); my_option m_option_structure; private: void call_callbacks(char* argument); std::vector*> m_callbacks; I_option_changed_listener* m_option_changed_listener; friend class Abstract_options_provider; }; template Abstract_option::~Abstract_option() { my_free((void*)this->m_option_structure.name); my_free((void*)this->m_option_structure.comment); for (std::vector*>::iterator it= this->m_callbacks.begin(); it != this->m_callbacks.end(); it++) { delete *it; } } template T_type* Abstract_option::add_callback( Mysql::I_callable* callback) { this->m_callbacks.push_back(callback); return (T_type*)this; } template T_type* Abstract_option::set_short_character( char code) { // Change optid to new one uint32 old_optid= this->m_option_structure.id; this->m_option_structure.id= (int)code; // Inform that it has changed if (this->m_option_changed_listener != NULL) { this->m_option_changed_listener->notify_option_optid_changed( this, old_optid); } return (T_type*)this; } template Abstract_option::Abstract_option(void* value, ulong var_type, std::string name, std::string description, uint64 default_value) : m_option_changed_listener(NULL) { this->m_option_structure.block_size= 0; this->m_option_structure.max_value= 0; this->m_option_structure.min_value= 0; this->m_option_structure.sub_size= 0; this->m_option_structure.typelib= NULL; this->m_option_structure.u_max_value= NULL; this->m_option_structure.app_type= this; this->m_option_structure.arg_type= REQUIRED_ARG; this->m_option_structure.comment= my_strdup( PSI_NOT_INSTRUMENTED, description.c_str(), MYF(MY_FAE)); // This in future can be changed to atomic operation (compare_and_exchange) this->m_option_structure.id= Abstract_option::last_optid; Abstract_option::last_optid++; ; this->m_option_structure.def_value= default_value; this->m_option_structure.name= my_strdup( PSI_NOT_INSTRUMENTED, name.c_str(), MYF(MY_FAE)); /* TODO mbabij 15-04-2014: this is based on previous usages of my_option. Everyone sets this the same as my_option::value, explain why. */ this->m_option_structure.u_max_value= value; this->m_option_structure.value= value; this->m_option_structure.var_type= var_type; } template my_option Abstract_option::get_my_option() { return this->m_option_structure; } template void Abstract_option::set_option_changed_listener( I_option_changed_listener* listener) { DBUG_ASSERT(this->m_option_changed_listener == NULL); this->m_option_changed_listener= listener; } template void Abstract_option::call_callbacks( char* argument) { std::vector*>::iterator callback_it; for (callback_it= this->m_callbacks.begin(); callback_it != this->m_callbacks.end(); callback_it++) { (**callback_it)(argument); } } } } } } #endif