list_impl.h
11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/**
* \file scot/list_impl.h
* \author Georg Steffers <georg@steffers.org>
* \brief Macro which creates functions for typesafe lists by templates.
*
* This combines the macro definitions in \link scot/list_man.h scot/list_man.h
* \endlink, \link scot/list_mod.h scot/list_mod.h \endlink and \link
* scot/list_nav.h scot/list_nav.h\endlink into one macro that is
* normally called within a c file that wants to use lists, as it provides
* you with all functions neccesary for list handling.\n
* Additionally the whole errorhandling code for lists is here. For that
* there are some function prototypes of functions implemented in
* \link list.c\endlink here. These functions do error output or will
* throw exceptions. Which function is called depends on if
* \link exception.c::USE_NO_EXCEPTIONS USE_NO_EXCEPTIONS\endlink is set at
* include time of this file, or not.
*
* Copyright (C)2006 Georg Steffers <georg@steffers.org>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 LIST_IMPL_H
#define LIST_IMPL_H
#include <scot/exception.h>
#include <scot/scot_types.h>
/**
* \internal
* \param type the datatype that this queue code should handle.
* \param a a variable holding a pointer to queue_[type]_node_t.
*
* \pre Type must be a single word typename. If one wants
* to use e.g. lists of structs one has to use typedef
* to create a single word type name like this:
* typedef struct mystruct_t mystruct_t;
* a must be a valid pointer to a queue_[type]_node_t.
* \returns \a a cast to a pointer of list_[type]_node_t.
* \post None
*
* \brief Cast a pointer to list_[type]_node_t.
*
* FIXME: I should check better the validity of \a a.
*/
#define LIST(type, a) (list_ ## type ## _node_t *) (a)
void list_error_print (const char *, int, int);
void list_warning_print (const char *, int, int);
void list_error_throw (const char *, int, int);
void list_warning_throw (const char *, int, int);
void * list_malloc_print (SIZE_T, const char *, int);
void list_check_null_print (const void *, const char *, int);
void * list_malloc_throw (SIZE_T, const char *, int);
void list_check_null_throw (const void *, const char *, int);
#ifdef USE_NO_EXCEPTION
# define LIST_ERROR(file, line, id) \
list_error_print ((file), (line), (id))
# define LIST_WARNING(file, line, id) \
list_warning_print ((file), (line), (id))
# define LIST_MALLOC(size, file, line) \
list_malloc_print ((size), (file), (line))
# define LIST_CHECK_NULL(val, file, line) \
list_check_null_print ((void *) (val), (file), (line))
# define LIST_EXC_START
# define LIST_EXC_END(file, line, id)
#else
/**
* \internal
* \param file filename of the file where the error occured.
* \param line line in the file where the error occured.
* \param id list error id.
*
* \brief print or thow an error
*/
# define LIST_ERROR(file, line, id) \
list_error_throw ((file), (line), (id))
/**
* \internal
* \param file filename of the file where the error occured.
* \param line line in the file where the error occured.
* \param id list error id.
*
* \brief print or throw a warning
*/
# define LIST_WARNING(file, line, id) \
list_warning_throw ((file), (line), (id))
/**
* \internal
* \param size the amount of memory that should be reserved.
* \param file filename of the file where this is called.
* \param line line in the file where this is called.
*
* \brief list malloc wrapper
*
* A malloc wrapper which either print an error or throw
* an exception.
*/
# define LIST_MALLOC(size, file, line) \
list_malloc_throw ((size), (file), (line))
/**
* \internal
* \param val variable that should be check for NULL.
* \param file filename of the file where this is called.
* \param line line in the file where this is called.
*
* \brief this checks if val is null
*/
# define LIST_CHECK_NULL(val, file, line) \
list_check_null_throw ((void *) (val), (file), (line))
/**
* \internal
* \brief start exception environment in generated list function.
*/
# define LIST_EXC_START \
{ \
excenv_t *ee; \
TRY {
/**
* \internal
* \brief end the exception environment of the generated list function.
*
* This ends the exception environment in the generated list
* function, that was started with LIST_EXC_START.
* Any exception that had occured will be forwarded in the upper
* exception environment and if exceptions had occured a new one
* will be thrown to the exception environment indicating that the
* function fails.
*/
# define LIST_EXC_END(file, line, id) \
} \
CATCH (ee) \
{ \
forward_all_exceptions (ee); \
list_error_throw ((file), (line), (id)); \
} \
}
#endif /* USE_NO_EXCEPTION */
extern const char *list_err_msg[];
extern const char *list_wrn_msg[];
struct list_node_t
{
const char _ [sizeof (struct {
const void *e;
const void *prev;
const void *next;
})];
};
#ifdef GEN_LOCAL
/**
* \internal
* \brief make functions static or not dependig on if GEN_LOCAL was
* defined or not.
*/
# define STATIC static
#else
# define STATIC
#endif
#include "list_man.h"
#include "list_nav.h"
#include "list_mod.h"
/**
* \param type the datatype that this list code should handle.
* \pre Type must be a single word typename. If one wants
* to use e.g. lists of structs one has to use typedef
* to create a single word type name like this:
* typedef struct mystruct_t mystruct_t;
* \return Nothing
* \post The functions, struct and globals to handle typesave
* lists for the given datatype are generated within the
* calling build file.
* FIXME: This seems not threadsafe to me, as the globals
* are used within all threads. Actually one could work
* around this because normally it is enough to set the
* comparison functions once and dont touch them anymore
* but it might be neccesary to compare elements within
* the list differently in different threads.
*
* \brief this creates all functions, structs and globals needed for a
* typesafe list of a given \a type.
*
* In detail the following is created by this macro:\n
* \li <b>struct list_[type]_node_t</b>: This is the structure a list
* is constructed of. A representation of a double linked list node with
* a pointer to the element it contains, a pointer to the next and a pointer
* to the previous element in the list. This list implementation uses a kind
* of a ringlist, that is the next pointer of the last node in the list
* and the prev pointer in the first element of the list points to the anchor.
* Thus in an empty list prev and next of the anchor both points to the
* anchor.
* \li <b>int list_[type]_default_cmp ()</b>: This is the default
* comparison function for lists. It simply compares the adresses of two
* elements. At list initialization list_[type]_compare() is set to this.
* \li <b>list_[type]_cmp_fptr list_[type]_compare</b>: This pointer
* to a function that compares list elements is used within the generated
* list functions.
* \li <b>list_[type]_elem_free_fptr list_[type]_elem_free</b>: This pointer
* , if set to non NULL, is used in list_[type]_delete() to free an
* element within a node before deleting the node. At initial time of
* the list code this is set to NULL, thus elements are not freed at all.
* (This is ok when stack variables are used, else one should at least
* set list_[type]_elem_free to free().)
* \li all functions defined in \link scot/list_man.h list_man.h\endlink,
* \link scot/list_mod.h list_mod.h\endlink and
* \link scot/list_nav.h list_nav.h\endlink.
*/
#define GEN_LIST_IMPL(type) \
struct list_ ## type ## _node_t \
{ \
const type *e; \
struct list_ ## type ## _node_t *prev; \
struct list_ ## type ## _node_t *next; \
}; \
\
STATIC \
int list_ ## type ## _default_cmp ( \
const type * a, \
const type * b) \
{ \
return (a==b)?0:(a<b)?-1:1; \
} \
\
STATIC \
list_ ## type ## _cmp_fptr \
list_ ## type ## _compare = list_ ## type ## _default_cmp; \
STATIC \
list_ ## type ## _elem_free_fptr \
list_ ## type ## _elem_free = NULL; \
\
GEN_LIST_MANAGEMENT (type); \
GEN_LIST_NAVIGATION (type); \
GEN_LIST_MODIFY (type);
#endif /* LIST_IMPL_H */