source: subversion/applications/utils/export/osm2pgsql/keyvals.c @ 15536

Last change on this file since 15536 was 14843, checked in by tomhughes, 11 years ago

Initial work on generating a gazetteer database.

File size: 4.6 KB
Line 
1/* Common key-value list processing
2 *
3 * Used as a small general purpose store for
4 * tags, segment lists etc
5 *
6 */
7#define USE_TREE
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <assert.h>
13#include "keyvals.h"
14
15#ifdef USE_TREE
16#include "text-tree.h"
17#endif
18
19void initList(struct keyval *head)
20{
21    assert(head);
22
23    head->next = head;
24    head->prev = head;
25    head->key = NULL;
26    head->value = NULL;
27}
28
29void freeItem(struct keyval *p)
30{
31    if (!p) 
32        return;
33
34#ifdef USE_TREE
35    text_release(tree_ctx, p->key);
36    text_release(tree_ctx, p->value);
37#else
38    free(p->key);
39    free(p->value);
40#endif
41    free(p);
42}
43
44
45unsigned int countList(struct keyval *head) 
46{
47    struct keyval *p;
48    unsigned int count = 0;     
49
50    if (!head) 
51        return 0;
52
53    p = head->next;
54    while(p != head) {
55        count++;
56        p = p->next;
57    }
58    return count;
59}
60
61int listHasData(struct keyval *head) 
62{
63    if (!head) 
64        return 0;
65
66    return (head->next != head);
67}
68
69
70char *getItem(struct keyval *head, const char *name)
71{
72    struct keyval *p;
73
74    if (!head) 
75        return NULL;
76
77    p = head->next;
78    while(p != head) {
79        if (!strcmp(p->key, name))
80            return p->value;
81        p = p->next;
82    }
83    return NULL;
84}       
85
86struct keyval *firstItem(struct keyval *head)
87{
88    if (head == NULL || head == head->next)
89        return NULL;
90
91    return head->next;
92}
93
94struct keyval *nextItem(struct keyval *head, struct keyval *item)
95{
96    if (item->next == head)
97        return NULL;
98
99    return item->next;
100}
101
102/* Pulls all items from list which match this prefix
103 * note: they are removed from the original list an returned in a new one
104 */
105struct keyval *getMatches(struct keyval *head, const char *name)
106{
107    struct keyval *out = NULL;
108    struct keyval *p;
109
110    if (!head) 
111        return NULL;
112
113    out = malloc(sizeof(struct keyval));
114    if (!out)
115        return NULL;
116
117    initList(out);
118    p = head->next;
119    while(p != head) {
120        struct keyval *next = p->next;
121        if (!strncmp(p->key, name, strlen(name))) {
122            //printf("match: %s=%s\n", p->key, p->value);
123            p->next->prev = p->prev;
124            p->prev->next = p->next;
125            pushItem(out, p);
126        }
127        p = next;
128    }
129
130    if (listHasData(out))
131        return out;
132
133    free(out);
134    return NULL;
135}
136
137void updateItem(struct keyval *head, const char *name, const char *value)
138{
139    struct keyval *item;
140
141    if (!head) 
142        return;
143
144    item = head->next;
145    while(item != head) {
146        if (!strcmp(item->key, name)) {
147#ifdef USE_TREE
148            text_release(tree_ctx, item->value);
149            item->value = (char *)text_get(tree_ctx,value);
150#else
151            free(item->value);
152            item->value = strdup(value);
153#endif
154            return;
155        }
156        item = item->next;
157    }
158    addItem(head, name, value, 0);
159}
160
161
162struct keyval *popItem(struct keyval *head)
163{
164    struct keyval *p;
165
166    if (!head) 
167        return NULL;
168 
169    p = head->next;
170    if (p == head)
171        return NULL;
172
173    head->next = p->next;
174    p->next->prev = head;
175
176    p->next = NULL;
177    p->prev = NULL;
178
179    return p;
180}       
181
182
183void pushItem(struct keyval *head, struct keyval *item)
184{
185    assert(head);
186    assert(item);
187 
188    item->next = head;
189    item->prev = head->prev;
190    head->prev->next = item;
191    head->prev = item;
192}       
193
194int addItem(struct keyval *head, const char *name, const char *value, int noDupe)
195{
196    struct keyval *item;
197
198    assert(head);
199    assert(name);
200    assert(value);
201
202    if (noDupe) {
203        item = head->next;
204        while (item != head) {
205            if (!strcmp(item->value, value) && !strcmp(item->key, name))
206                return 1;
207            item = item->next;
208        }
209    }
210
211    item = malloc(sizeof(struct keyval));
212
213    if (!item) {
214        fprintf(stderr, "Error allocating keyval\n");
215        return 2;
216    }
217
218#ifdef USE_TREE
219    item->key   = (char *)text_get(tree_ctx,name);
220    item->value = (char *)text_get(tree_ctx,value);
221#else
222    item->key   = strdup(name);
223    item->value = strdup(value);
224#endif
225
226#if 1
227    // Add to head
228    item->next = head->next;
229    item->prev = head;
230    head->next->prev = item;
231    head->next = item;
232#else
233    // Add to tail
234    item->prev = head->prev;
235    item->next = head;
236    head->prev->next = item;
237    head->prev = item;
238#endif
239    return 0;
240}
241
242void resetList(struct keyval *head) 
243{
244    struct keyval *item;
245       
246    while((item = popItem(head))) 
247        freeItem(item);
248}
249
250void cloneList( struct keyval *target, struct keyval *source )
251{
252  struct keyval *ptr;
253  for( ptr = source->next; ptr != source; ptr=ptr->next )
254    addItem( target, ptr->key, ptr->value, 0 );
255}
Note: See TracBrowser for help on using the repository browser.