source: subversion/applications/utils/planet.osm/C/keyvals.c @ 13543

Last change on this file since 13543 was 4691, checked in by jonb, 12 years ago

planet.c: Clone of planet.rb, runs at about 10 times the speed of the ruby script

File size: 4.1 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
86/* Pulls all items from list which match this prefix
87 * note: they are removed from the original list an returned in a new one
88 */
89struct keyval *getMatches(struct keyval *head, const char *name)
90{
91    struct keyval *out = NULL;
92    struct keyval *p;
93
94    if (!head) 
95        return NULL;
96
97    out = malloc(sizeof(struct keyval));
98    if (!out)
99        return NULL;
100
101    initList(out);
102    p = head->next;
103    while(p != head) {
104        struct keyval *next = p->next;
105        if (!strncmp(p->key, name, strlen(name))) {
106            //printf("match: %s=%s\n", p->key, p->value);
107            p->next->prev = p->prev;
108            p->prev->next = p->next;
109            pushItem(out, p);
110        }
111        p = next;
112    }
113
114    if (listHasData(out))
115        return out;
116
117    free(out);
118    return NULL;
119}
120
121void updateItem(struct keyval *head, const char *name, const char *value)
122{
123    struct keyval *item;
124
125    if (!head) 
126        return;
127
128    item = head->next;
129    while(item != head) {
130        if (!strcmp(item->key, name)) {
131#ifdef USE_TREE
132            text_release(tree_ctx, item->value);
133            item->value = (char *)text_get(tree_ctx,value);
134#else
135            free(item->value);
136            item->value = strdup(value);
137#endif
138            return;
139        }
140        item = item->next;
141    }
142    addItem(head, name, value, 0);
143}
144
145
146struct keyval *popItem(struct keyval *head)
147{
148    struct keyval *p;
149
150    if (!head) 
151        return NULL;
152 
153    p = head->next;
154    if (p == head)
155        return NULL;
156
157    head->next = p->next;
158    p->next->prev = head;
159
160    p->next = NULL;
161    p->prev = NULL;
162
163    return p;
164}       
165
166
167void pushItem(struct keyval *head, struct keyval *item)
168{
169    assert(head);
170    assert(item);
171 
172    item->next = head;
173    item->prev = head->prev;
174    head->prev->next = item;
175    head->prev = item;
176}       
177
178int addItem(struct keyval *head, const char *name, const char *value, int noDupe)
179{
180    struct keyval *item;
181
182    assert(head);
183    assert(name);
184    assert(value);
185
186    if (noDupe) {
187        item = head->next;
188        while (item != head) {
189            if (!strcmp(item->value, value) && !strcmp(item->key, name))
190                return 1;
191            item = item->next;
192        }
193    }
194
195    item = malloc(sizeof(struct keyval));
196
197    if (!item) {
198        fprintf(stderr, "Error allocating keyval\n");
199        return 2;
200    }
201
202#ifdef USE_TREE
203    item->key   = (char *)text_get(tree_ctx,name);
204    item->value = (char *)text_get(tree_ctx,value);
205#else
206    item->key   = strdup(name);
207    item->value = strdup(value);
208#endif
209
210#if 0
211    item->next = head->next;
212    item->prev = head;
213    head->next->prev = item;
214    head->next = item;
215#else
216    item->next = head;
217    item->prev = head->prev;
218    head->prev->next = item;
219    head->prev = item;
220#endif
221    return 0;
222}
223
224void resetList(struct keyval *head) 
225{
226    struct keyval *item;
227       
228    while((item = popItem(head))) 
229        freeItem(item);
230}
231
Note: See TracBrowser for help on using the repository browser.