source: subversion/applications/utils/coastcheck/keyvals.c @ 9744

Last change on this file since 9744 was 6729, checked in by martinvoosterhout, 12 years ago

Initial commit of the coastline checker. It's been used for a while now
successfully.

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