Change tui_data_item_window::content to be a unique_xmalloc_ptr
[external/binutils.git] / gdb / registry.h
1 /* Macros for general registry objects.
2
3    Copyright (C) 2011-2019 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #ifndef REGISTRY_H
21 #define REGISTRY_H
22
23 #include <type_traits>
24
25 /* The macros here implement a template type and functions for
26    associating some user data with a container object.
27
28    A registry is associated with a struct tag name.  To attach a
29    registry to a structure, use DEFINE_REGISTRY.  This takes the
30    structure tag and an access method as arguments.  In the usual
31    case, where the registry fields appear directly in the struct, you
32    can use the 'REGISTRY_FIELDS' macro to declare the fields in the
33    struct definition, and you can pass 'REGISTRY_ACCESS_FIELD' as the
34    access argument to DEFINE_REGISTRY.  In other cases, use
35    REGISTRY_FIELDS to define the fields in the appropriate spot, and
36    then define your own accessor to find the registry field structure
37    given an instance of your type.
38
39    The API user requests a key from a registry during gdb
40    initialization.  Later this key can be used to associate some
41    module-specific data with a specific container object.
42
43    The exported API is best used via the wrapper macros:
44    
45    - register_TAG_data(TAG)
46    Get a new key for the container type TAG.
47    
48    - register_TAG_data_with_cleanup(TAG, SAVE, FREE)
49    Get a new key for the container type TAG.
50    SAVE and FREE are defined as void (*) (struct TAG *object, void *data)
51    When the container object OBJECT is destroyed, first all registered SAVE
52    functions are called.
53    Then all FREE functions are called.
54    Either or both may be NULL.  DATA is the data associated with the
55    container object OBJECT.
56    
57    - clear_TAG_data(TAG, OBJECT)
58    Clear all the data associated with OBJECT.  Should be called by the
59    container implementation when a container object is destroyed.
60    
61    - set_TAG_data(TAG, OBJECT, KEY, DATA)
62    Set the data on an object.
63    
64    - TAG_data(TAG, OBJECT, KEY)
65    Fetch the data for an object; returns NULL if it has not been set.
66 */
67
68 /* This structure is used in a container to hold the data that the
69    registry uses.  */
70
71 struct registry_fields
72 {
73   void **data;
74   unsigned num_data;
75 };
76
77 /* This macro is used in a container struct definition to define the
78    fields used by the registry code.  */
79
80 #define REGISTRY_FIELDS                         \
81   struct registry_fields registry_data
82
83 /* A convenience macro for the typical case where the registry data is
84    kept as fields of the object.  This can be passed as the ACCESS
85    method to DEFINE_REGISTRY.  */
86
87 #define REGISTRY_ACCESS_FIELD(CONTAINER) \
88   (CONTAINER)
89
90 /* Opaque type representing a container type with a registry.  This
91    type is never defined.  This is used to factor out common
92    functionality of all struct tag names into common code.  IOW,
93    "struct tag name" pointers are cast to and from "struct
94    registry_container" pointers when calling the common registry
95    "backend" functions.  */
96 struct registry_container;
97
98 /* Registry callbacks have this type.  */
99 typedef void (*registry_data_callback) (struct registry_container *, void *);
100
101 struct registry_data
102 {
103   unsigned index;
104   registry_data_callback save;
105   registry_data_callback free;
106 };
107
108 struct registry_data_registration
109 {
110   struct registry_data *data;
111   struct registry_data_registration *next;
112 };
113
114 struct registry_data_registry
115 {
116   struct registry_data_registration *registrations;
117   unsigned num_registrations;
118 };
119
120 /* Registry backend functions.  Client code uses the frontend
121    functions defined by DEFINE_REGISTRY below instead.  */
122
123 const struct registry_data *register_data_with_cleanup
124   (struct registry_data_registry *registry,
125    registry_data_callback save,
126    registry_data_callback free);
127
128 void registry_alloc_data (struct registry_data_registry *registry,
129                           struct registry_fields *registry_fields);
130
131 /* Cast FUNC and CONTAINER to the real types, and call FUNC, also
132    passing DATA.  */
133 typedef void (*registry_callback_adaptor) (registry_data_callback func,
134                                            struct registry_container *container,
135                                            void *data);
136
137 void registry_clear_data (struct registry_data_registry *data_registry,
138                           registry_callback_adaptor adaptor,
139                           struct registry_container *container,
140                           struct registry_fields *fields);
141
142 void registry_container_free_data (struct registry_data_registry *data_registry,
143                                    registry_callback_adaptor adaptor,
144                                    struct registry_container *container,
145                                    struct registry_fields *fields);
146
147 void registry_set_data (struct registry_fields *fields,
148                         const struct registry_data *data,
149                         void *value);
150
151 void *registry_data (struct registry_fields *fields,
152                      const struct registry_data *data);
153
154 /* Define a new registry implementation.  */
155
156 #define DEFINE_REGISTRY(TAG, ACCESS)                                    \
157 struct registry_data_registry TAG ## _data_registry = { NULL, 0 };      \
158                                                                         \
159 const struct TAG ## _data *                                             \
160 register_ ## TAG ## _data_with_cleanup (void (*save) (struct TAG *, void *), \
161                                         void (*free) (struct TAG *, void *)) \
162 {                                                                       \
163   return (struct TAG ## _data *)                                        \
164     register_data_with_cleanup (&TAG ## _data_registry,                 \
165                                 (registry_data_callback) save,          \
166                                 (registry_data_callback) free);         \
167 }                                                                       \
168                                                                         \
169 const struct TAG ## _data *                                             \
170 register_ ## TAG ## _data (void)                                        \
171 {                                                                       \
172   return register_ ## TAG ## _data_with_cleanup (NULL, NULL);           \
173 }                                                                       \
174                                                                         \
175 static void                                                             \
176 TAG ## _alloc_data (struct TAG *container)                              \
177 {                                                                       \
178   struct registry_fields *rdata = &ACCESS (container)->registry_data;   \
179                                                                         \
180   registry_alloc_data (&TAG ## _data_registry, rdata);                  \
181 }                                                                       \
182                                                                         \
183 static void                                                             \
184 TAG ## registry_callback_adaptor (registry_data_callback func,          \
185                                   struct registry_container *container, \
186                                   void *data)                           \
187 {                                                                       \
188   struct TAG *tagged_container = (struct TAG *) container;              \
189                                                                         \
190   registry_ ## TAG ## _callback tagged_func                             \
191     = (registry_ ## TAG ## _callback) func;                             \
192                                                                         \
193   tagged_func (tagged_container, data);                                 \
194 }                                                                       \
195                                                                         \
196 void                                                                    \
197 clear_ ## TAG ## _data (struct TAG *container)                          \
198 {                                                                       \
199   struct registry_fields *rdata = &ACCESS (container)->registry_data;   \
200                                                                         \
201   registry_clear_data (&TAG ## _data_registry,                          \
202                        TAG ## registry_callback_adaptor,                \
203                        (struct registry_container *) container,         \
204                        rdata);                                          \
205 }                                                                       \
206                                                                         \
207 static void                                                             \
208 TAG ## _free_data (struct TAG *container)                               \
209 {                                                                       \
210   struct registry_fields *rdata = &ACCESS (container)->registry_data;   \
211                                                                         \
212   registry_container_free_data (&TAG ## _data_registry,                 \
213                                 TAG ## registry_callback_adaptor,       \
214                                 (struct registry_container *) container, \
215                                 rdata);                                 \
216 }                                                                       \
217                                                                         \
218 void                                                                    \
219 set_ ## TAG ## _data (struct TAG *container,                            \
220                       const struct TAG ## _data *data,                  \
221                       void *value)                                      \
222 {                                                                       \
223   struct registry_fields *rdata = &ACCESS (container)->registry_data;   \
224                                                                         \
225   registry_set_data (rdata,                                             \
226                      (struct registry_data *) data,                     \
227                      value);                                            \
228 }                                                                       \
229                                                                         \
230 void *                                                                  \
231 TAG ## _data (struct TAG *container, const struct TAG ## _data *data)   \
232 {                                                                       \
233   struct registry_fields *rdata = &ACCESS (container)->registry_data;   \
234                                                                         \
235   return registry_data (rdata,                                          \
236                         (struct registry_data *) data);                 \
237 }
238
239
240 /* External declarations for the registry functions.  */
241
242 #define DECLARE_REGISTRY(TAG)                                           \
243 struct TAG ## _data;                                                    \
244 typedef void (*registry_ ## TAG ## _callback) (struct TAG *, void *);   \
245 extern const struct TAG ## _data *register_ ## TAG ## _data (void);     \
246 extern const struct TAG ## _data *register_ ## TAG ## _data_with_cleanup \
247  (registry_ ## TAG ## _callback save, registry_ ## TAG ## _callback free); \
248 extern void clear_ ## TAG ## _data (struct TAG *);                      \
249 extern void set_ ## TAG ## _data (struct TAG *,                         \
250                                   const struct TAG ## _data *data,      \
251                                   void *value);                         \
252 extern void *TAG ## _data (struct TAG *,                                \
253                            const struct TAG ## _data *data);            \
254                                                                         \
255 template<typename DATA, typename Deleter = std::default_delete<DATA>>   \
256 class TAG ## _key                                                       \
257 {                                                                       \
258 public:                                                                 \
259                                                                         \
260   TAG ## _key ()                                                        \
261     : m_key (register_ ## TAG ## _data_with_cleanup (nullptr,           \
262                                                      cleanup))          \
263   {                                                                     \
264   }                                                                     \
265                                                                         \
266   DATA *get (struct TAG *obj) const                                     \
267   {                                                                     \
268     return (DATA *) TAG ## _data (obj, m_key);                          \
269   }                                                                     \
270                                                                         \
271   void set (struct TAG *obj, DATA *data) const                          \
272   {                                                                     \
273     set_ ## TAG ## _data (obj, m_key, data);                            \
274   }                                                                     \
275                                                                         \
276   template<typename Dummy = DATA *, typename... Args>                   \
277   typename std::enable_if<std::is_same<Deleter,                         \
278                                        std::default_delete<DATA>>::value, \
279                           Dummy>::type                                  \
280   emplace (struct TAG *obj, Args &&...args) const                       \
281   {                                                                     \
282     DATA *result = new DATA (std::forward<Args> (args)...);             \
283     set (obj, result);                                                  \
284     return result;                                                      \
285   }                                                                     \
286                                                                         \
287   void clear (struct TAG *obj) const                                    \
288   {                                                                     \
289     DATA *datum = get (obj);                                            \
290     if (datum != nullptr)                                               \
291       {                                                                 \
292         cleanup (obj, datum);                                           \
293         set (obj, nullptr);                                             \
294       }                                                                 \
295   }                                                                     \
296                                                                         \
297 private:                                                                \
298                                                                         \
299   static void cleanup (struct TAG *obj, void *arg)                      \
300   {                                                                     \
301     DATA *datum = (DATA *) arg;                                         \
302     Deleter d;                                                          \
303     d (datum);                                                          \
304   }                                                                     \
305                                                                         \
306   const struct TAG ## _data *m_key;                                     \
307 };
308
309 #endif /* REGISTRY_H */