ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/vector.h
Revision: 1.4
Committed: Mon Apr 5 00:45:17 2004 UTC (20 years, 1 month ago) by ats
Content type: text/plain
Branch: MAIN
Changes since 1.3: +17 -3 lines
Log Message:
Fix the strict-aliasing warnings.

This is even uglier than the previous code, since it pushes a test for a
sentinel value into the VECTOR_RESIZE macro. I'm pretty certain that the
pointer-to-static-used-as-sentinel is my own invention. I'm not entirely
convinced that it's a good idea, but I can't see anything technically
wrong with it...

File Contents

# User Rev Content
1 ats 1.1 #include <stdlib.h>
2    
3     typedef void (*vector_init_function)(void *item);
4     typedef void (*vector_destroy_function)(void *item);
5    
6     typedef struct {
7     size_t item_size;
8     int used_count;
9     int alloc_count;
10     int block_size;
11     vector_init_function init_fn;
12     vector_destroy_function destroy_fn;
13     } vector_header;
14    
15 ats 1.2 #define VECTOR_HEADER(name, item_type, block_size, init_fn, destroy_fn) \
16 ats 1.1 vector_header name##_header = { \
17     sizeof(item_type), \
18     0, \
19     0, \
20     block_size, \
21     (vector_init_function) init_fn, \
22     (vector_destroy_function) destroy_fn \
23     }
24    
25 ats 1.4 /* A pointer value that won't be returned by malloc, and isn't NULL, so can be
26     * used as a sentinel by allocation routines that need to return NULL
27     * sometimes. */
28     extern char statgrab_vector_sentinel_value;
29     static void *statgrab_vector_sentinel = &statgrab_vector_sentinel_value;
30    
31     /* Internal function to resize the vector. Ideally it would take void ** as the
32     * first parameter, but ANSI strict-aliasing rules would then prevent it from
33     * doing anything with it, so we return a sentinel value as above instead if
34     * allocation fails. */
35     void *statgrab_vector_resize(void *vector, vector_header *h, int count);
36 ats 1.2
37     /* Declare a vector. Specify the init/destroy functions as NULL if you don't
38     * need them. The block size is how many items to allocate at once. */
39     #define VECTOR_DECLARE(name, item_type, block_size, init_fn, destroy_fn) \
40     item_type *name = NULL; \
41     VECTOR_HEADER(name, item_type, block_size, init_fn, destroy_fn)
42    
43     /* As VECTOR_DECLARE, but for a static vector. */
44     #define VECTOR_DECLARE_STATIC(name, item_type, block_size, init_fn, destroy_fn) \
45     static item_type *name = NULL; \
46     static VECTOR_HEADER(name, item_type, block_size, init_fn, destroy_fn)
47    
48 ats 1.1 /* Return the current size of a vector. */
49     #define VECTOR_SIZE(name) \
50     name##_header.used_count
51    
52     /* Resize a vector. Returns 0 on success, -1 on out-of-memory. On
53     * out-of-memory, the old contents of the vector will be destroyed and the old
54 ats 1.4 * vector will be freed.
55     *
56     * This is ugly because it needs to check for the sentinel value.
57     */
58 ats 1.1 #define VECTOR_RESIZE(name, num_items) \
59 ats 1.4 (((name = statgrab_vector_resize((char *) name, &name##_header, num_items)) \
60     == statgrab_vector_sentinel) ? -1 : 0)
61 ats 1.1
62     /* Free a vector, destroying its contents. */
63     #define VECTOR_FREE(name) \
64     VECTOR_RESIZE(name, 0)
65