File: loptr.c

package info (click to toggle)
python-clips 1.0.7.348%2Bclips-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,376 kB
  • ctags: 2,544
  • sloc: ansic: 17,065; python: 5,668; sh: 20; makefile: 12
file content (194 lines) | stat: -rw-r--r-- 5,258 bytes parent folder | download | duplicates (3)
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
/* loptr.c
 *  Simple list-of-pointers handling library; this library is intended to
 *  be directly included in the source file that would use it, without prior
 *  or separated compilation. We use a hash table not just because we expect
 *  to be likely to have many records in the list, but also hoping that in
 *  many cases this will make it faster to find out whether or not a pointer
 *  is already present.
 *
 * Even though this library is useless, it's however released under the LGPL.
 *
 * $Id: loptr.c 340 2008-02-21 00:39:34Z Franz $
 * (c) 2008 - Francesco Garosi/JKS
 */



/* the kind of integers we will be dealing with */
#define LOPTR_INT unsigned long
#define LOPTR_BOOL int
#define LOPTR_TRUE 1
#define LOPTR_FALSE 0

/* the following can be helpful when allocating objects */
#ifdef USE_PYTHON_MEMMGR
#define LOPTR_NEW(x) PyMem_New(x, 1)
#define LOPTR_DELETE(x) PyMem_Del(x)
#else
#define LOPTR_NEW(x) ((x *)malloc(sizeof(x)))
#define LOPTR_DELETE(x) free(x)
#endif

/* these functions are intended to be very fast and inlined */
#ifdef F_INLINE
#define LOPTR_INLINE F_INLINE
#else
#define LOPTR_INLINE
#endif /* F_INLINE */

/* size of hash table for sublists of pointers, should be a prime */
#ifndef STRAY_FACTS_TABLE_SIZE
#define STRAY_FACTS_TABLE_SIZE 211
#endif
#define LOPTR_HASH_TABLE_SIZE ((LOPTR_INT)STRAY_FACTS_TABLE_SIZE)
#define LOPTR_HASH(_x) (((LOPTR_INT)_x) % LOPTR_HASH_TABLE_SIZE)

/* decide whether or not to use register variables and pointers */
#ifdef USE_REGISTER_VARIABLES
#define LOPTR_REGISTER register
#else
#define LOPTR_REGISTER
#endif


/* will constitute the sublists of pointers */
typedef struct __struct_LOPTR_ITEM {
    void *elem;
    struct __struct_LOPTR_ITEM *next;
} LOPTR_ITEM;


/* type of function accepted by LOPTR_apply */
typedef LOPTR_BOOL(*LOPTR_FUNC)(void *);


/* give a standardized way to create a hash table */
#define LOPTR_HASH_TABLE(name) LOPTR_ITEM *name[LOPTR_HASH_TABLE_SIZE]
#define INIT_LOPTR_HASH_TABLE(name) \
	memset(name, 0, sizeof(LOPTR_ITEM *) * (LOPTR_HASH_TABLE_SIZE))
#define COPY_LOPTR_HASH_TABLE(dst, src) \
	memcpy((dst), (src), sizeof(LOPTR_ITEM *) * (LOPTR_HASH_TABLE_SIZE))


/* functions to transparently manage the list */

/* find an element */
static LOPTR_INLINE LOPTR_ITEM *LOPTR_find(LOPTR_ITEM **t, void *elem) {
    LOPTR_REGISTER LOPTR_ITEM *p = t[LOPTR_HASH(elem)];
    
    while(p) {
        if(p->elem == elem)
            return p;
        else
            p = p->next;
    }
    return NULL;
}

/* find the last item in the hash table for element */
static LOPTR_INLINE LOPTR_ITEM *LOPTR_lastitem(LOPTR_ITEM **t, void *elem) {
    LOPTR_REGISTER LOPTR_ITEM *p = t[LOPTR_HASH(elem)];
    
    if(p) {
        while(p->next != NULL)
            p = p->next;
        return p;
    } else
        return NULL;
}

/* append an element in the hash table */
static LOPTR_INLINE LOPTR_BOOL LOPTR_append(LOPTR_ITEM **t, void *elem) {
    LOPTR_ITEM *p = NULL, *q = NULL;
    
    if(LOPTR_find(t, elem))
        return LOPTR_FALSE;
    else {
        p = LOPTR_NEW(LOPTR_ITEM);
        p->elem = elem;
        p->next = NULL;
        q = LOPTR_lastitem(t, elem);
        if(q)
            q->next = p;
        else
            t[LOPTR_HASH(elem)] = p;
        return LOPTR_TRUE;
    }
}

/* remove an element from the hash table */
static LOPTR_INLINE LOPTR_BOOL LOPTR_remove(LOPTR_ITEM **t, void *elem) {
    int h = LOPTR_HASH(elem);
    LOPTR_REGISTER LOPTR_ITEM *p = t[h];
    LOPTR_ITEM *q = NULL;

    if(p) {
        if(p->elem == elem) {
            t[h] = p->next;  /* could be NULL */
            LOPTR_DELETE(p);
            return LOPTR_TRUE;
        } else {
            while(p) {
                q = p;
                p = p->next;
                if(p->elem == elem) {
                    q->next = p->next;  /* could be NULL either */
                    LOPTR_DELETE(p);
                    return LOPTR_TRUE;
                }
            }
        }
    }
    return LOPTR_FALSE;
}

/* apply a bool-returning function to list elements ignoring result */
static LOPTR_INLINE void LOPTR_apply(LOPTR_ITEM **t, LOPTR_FUNC f) {
    int i = 0;
    LOPTR_REGISTER LOPTR_ITEM *p = NULL;
    
    for(i = 0; i < LOPTR_HASH_TABLE_SIZE; i++) {
        p = t[i];
        while(p) {
            f(p->elem);
            p = p->next;
        }
    }
}

/* apply a bool-returning function to list elements returning failing result */
static LOPTR_INLINE void *LOPTR_test_apply(LOPTR_ITEM **t, LOPTR_FUNC f) {
    LOPTR_REGISTER int i = 0;
    LOPTR_REGISTER LOPTR_ITEM *p = NULL;
    
    for(i = 0; i < LOPTR_HASH_TABLE_SIZE; i++) {
        p = t[i];
        while(p) {
            if(!f(p->elem))
                return p->elem;
            p = p->next;
        }
    }
    return NULL;
}

/* reset a hash table (only leave the array) removing all possible lists */
static LOPTR_INLINE void LOPTR_reset_hash_table(LOPTR_ITEM **t) {
    LOPTR_REGISTER int i = 0;
    LOPTR_REGISTER LOPTR_ITEM *p = NULL;
    LOPTR_ITEM *q = NULL;
    
    for(i = 0; i < LOPTR_HASH_TABLE_SIZE; i++) {
        p = t[i];
        while(p) {
            q = p;
            p = p->next;
            LOPTR_DELETE(q);
        }
        t[i] = NULL;
    }
}



/* end. */