1 /*
2 Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef ABSTRACT_OPTION_INCLUDED
26 #define ABSTRACT_OPTION_INCLUDED
27
28 #include <string>
29 #include <vector>
30 #include "my_getopt.h"
31 #include "i_option_changed_listener.h"
32 #include "i_callable.h"
33
34
35 namespace Mysql{
36 namespace Tools{
37 namespace Base{
38 namespace Options{
39
40 class Abstract_options_provider;
41
42 /**
43 Abstract base with common option functionalities.
44 */
45 template<typename T_type> class Abstract_option : public I_option
46 {
47 public:
48 virtual ~Abstract_option();
49
50 /**
51 Adds new callback for this option for option_parsed() event to callback
52 chain.
53 I_Callable can be replaced with std::Function<void(char*)> once we get
54 one.
55 */
56 T_type* add_callback(Mysql::I_callable<void, char*>* callback);
57
58 /**
59 Sets optid to given character to make possible usage of short option
60 alternative.
61 */
62 T_type* set_short_character(char code);
63
64 protected:
65 /**
66 Constructs new option.
67 @param value Pointer to object to receive option value.
68 @param var_type my_getopt internal option type.
69 @param name Name of option. It is used in command line option name as
70 --name.
71 @param desription Description of option to be printed in --help.
72 @param default_value default value to be supplied to internal option
73 data structure.
74 */
75 Abstract_option(void* value, ulong var_type, std::string name,
76 std::string description, uint64 default_value);
77
78 /**
79 Returns my_getopt internal option data structure representing this option.
80 To be used by Abstract_options_provider when preparing options array to
81 return.
82 */
83 my_option get_my_option();
84
85 /**
86 Method to set listener on option changed events.
87 For use from Abstract_options_provider class only.
88 */
89 void set_option_changed_listener(I_option_changed_listener* listener);
90
91 my_option m_option_structure;
92
93 private:
94 void call_callbacks(char* argument);
95
96 std::vector<Mysql::I_callable<void, char*>*> m_callbacks;
97 I_option_changed_listener* m_option_changed_listener;
98
99 friend class Abstract_options_provider;
100 };
101
~Abstract_option()102 template<typename T_type> Abstract_option<T_type>::~Abstract_option()
103 {
104 my_free((void*)this->m_option_structure.name);
105 my_free((void*)this->m_option_structure.comment);
106
107 for (std::vector<Mysql::I_callable<void, char*>*>::iterator
108 it= this->m_callbacks.begin();
109 it != this->m_callbacks.end();
110 it++)
111 {
112 delete *it;
113 }
114 }
115
add_callback(Mysql::I_callable<void,char * > * callback)116 template<typename T_type> T_type* Abstract_option<T_type>::add_callback(
117 Mysql::I_callable<void, char*>* callback)
118 {
119 this->m_callbacks.push_back(callback);
120 return (T_type*)this;
121 }
122
set_short_character(char code)123 template<typename T_type> T_type* Abstract_option<T_type>::set_short_character(
124 char code)
125 {
126 // Change optid to new one
127 uint32 old_optid= this->m_option_structure.id;
128 this->m_option_structure.id= (int)code;
129
130 // Inform that it has changed
131 if (this->m_option_changed_listener != NULL)
132 {
133 this->m_option_changed_listener->notify_option_optid_changed(
134 this, old_optid);
135 }
136
137 return (T_type*)this;
138 }
139
Abstract_option(void * value,ulong var_type,std::string name,std::string description,uint64 default_value)140 template<typename T_type> Abstract_option<T_type>::Abstract_option(void* value,
141 ulong var_type, std::string name, std::string description,
142 uint64 default_value)
143 : m_option_changed_listener(NULL)
144 {
145 this->m_option_structure.block_size= 0;
146 this->m_option_structure.max_value= 0;
147 this->m_option_structure.min_value= 0;
148 this->m_option_structure.sub_size= 0;
149 this->m_option_structure.typelib= NULL;
150 this->m_option_structure.u_max_value= NULL;
151
152 this->m_option_structure.app_type= this;
153 this->m_option_structure.arg_type= REQUIRED_ARG;
154 this->m_option_structure.comment= my_strdup(
155 PSI_NOT_INSTRUMENTED, description.c_str(), MYF(MY_FAE));
156 // This in future can be changed to atomic operation (compare_and_exchange)
157 this->m_option_structure.id= Abstract_option::last_optid;
158 Abstract_option::last_optid++;
159 ;
160 this->m_option_structure.def_value= default_value;
161
162 this->m_option_structure.name= my_strdup(
163 PSI_NOT_INSTRUMENTED, name.c_str(), MYF(MY_FAE));
164 /*
165 TODO mbabij 15-04-2014: this is based on previous usages of my_option.
166 Everyone sets this the same as my_option::value, explain why.
167 */
168 this->m_option_structure.u_max_value= value;
169
170 this->m_option_structure.value= value;
171 this->m_option_structure.var_type= var_type;
172 }
173
get_my_option()174 template<typename T_type> my_option Abstract_option<T_type>::get_my_option()
175 {
176 return this->m_option_structure;
177 }
178
179 template<typename T_type> void
set_option_changed_listener(I_option_changed_listener * listener)180 Abstract_option<T_type>::set_option_changed_listener(
181 I_option_changed_listener* listener)
182 {
183 DBUG_ASSERT(this->m_option_changed_listener == NULL);
184
185 this->m_option_changed_listener= listener;
186 }
187
call_callbacks(char * argument)188 template<typename T_type> void Abstract_option<T_type>::call_callbacks(
189 char* argument)
190 {
191 std::vector<Mysql::I_callable<void, char*>*>::iterator callback_it;
192 for (callback_it= this->m_callbacks.begin();
193 callback_it != this->m_callbacks.end(); callback_it++)
194 {
195 (**callback_it)(argument);
196 }
197 }
198
199 }
200 }
201 }
202 }
203
204 #endif
205