more code for proplist handling
[wmaker-crm.git] / WINGs / proplist.c
blob1342e9037b47f2b44f47344a97063d91f2426a11
3 #include <string.h>
4 #include <stdarg.h>
6 #include "WUtil.h"
7 #include "wconfig.h"
11 typedef enum {
12 WPLString = 0x57504c01,
13 WPLData = 0x57504c02,
14 WPLArray = 0x57504c03,
15 WPLDictionary = 0x57504c04
16 } WPLType;
19 typedef struct W_PropList {
20 WPLType type;
22 union {
23 char *string;
24 WMData *data;
25 WMArray *array;
26 WMHashTable *dict;
27 } d;
29 int retainCount;
30 } W_PropList;
35 static unsigned hashPropList(WMPropList *plist);
40 typedef unsigned (*hashFunc)(const void*);
41 typedef Bool (*isEqualFunc)(const void*, const void*);
42 typedef void* (*retainFunc)(const void*);
43 typedef void (*releaseFunc)(const void*);
45 static const WMHashTableCallbacks WMPropListHashCallbacks = {
46 (hashFunc)hashPropList,
47 (isEqualFunc)WMArePropListsEqual,
48 (retainFunc)NULL,
49 (releaseFunc)NULL
52 static WMCompareDataProc *strCmp = (WMCompareDataProc*) strcmp;
56 static unsigned
57 hashPropList(WMPropList *plist)
59 unsigned ret = 0;
60 unsigned ctr = 0;
61 const char *key;
62 int i;
64 switch (plist->type) {
65 case WPLString:
66 key = plist->d.string;
67 while (*key) {
68 ret ^= *key++ << ctr;
69 ctr = (ctr + 1) % sizeof (char *);
71 return ret;
73 case WPLData:
74 key = WMDataBytes(plist->d.data);
75 for (i=0; i<WMGetDataLength(plist->d.data); i++) {
76 ret ^= key[i] << ctr;
77 ctr = (ctr + 1) % sizeof (char *);
79 return ret;
81 default:
82 wwarning(_("Only string or data is supported for a proplist dictionary key"));
83 wassertrv(False, 0);
84 break;
89 void
90 WMSetPropListStringComparer(WMCompareDataProc *comparer)
92 if (!comparer)
93 strCmp = (WMCompareDataProc*) strcmp;
94 else
95 strCmp = comparer;
99 WMPropList*
100 WMCreatePropListString(char *str)
102 WMPropList *plist;
104 wassertrv(str!=NULL, NULL);
106 plist = (WMPropList*)wmalloc(sizeof(W_PropList));
108 plist->type = WPLString;
109 plist->d.string = wstrdup(str);
110 plist->retainCount = 1;
112 return plist;
116 WMPropList*
117 WMCreatePropListDataWithBytes(unsigned char *bytes, unsigned int length)
119 WMPropList *plist;
121 wassertrv(bytes!=NULL, NULL);
123 plist = (WMPropList*)wmalloc(sizeof(W_PropList));
125 plist->type = WPLData;
126 plist->d.data = WMCreateDataWithBytes(bytes, length);
127 plist->retainCount = 1;
129 return plist;
133 WMPropList*
134 WMCreatePropListDataWithBytesNoCopy(unsigned char *bytes, unsigned int length,
135 WMFreeDataProc *destructor)
137 WMPropList *plist;
139 wassertrv(length!=0 && bytes!=NULL, NULL);
141 plist = (WMPropList*)wmalloc(sizeof(W_PropList));
143 plist->type = WPLData;
144 plist->d.data = WMCreateDataWithBytesNoCopy(bytes, length, destructor);
145 plist->retainCount = 1;
147 return plist;
151 WMPropList*
152 WMCreatePropListDataWithData(WMData *data)
154 WMPropList *plist;
156 wassertrv(data!=NULL, NULL);
158 plist = (WMPropList*)wmalloc(sizeof(W_PropList));
160 plist->type = WPLData;
161 plist->d.data = WMRetainData(data);
162 plist->retainCount = 1;
164 return plist;
168 WMPropList*
169 WMCreatePropListArrayFromElements(WMPropList *elem, ...)
171 WMPropList *plist, *nelem;
172 va_list ap;
174 plist = (WMPropList*)wmalloc(sizeof(W_PropList));
175 plist->type = WPLArray;
176 plist->d.array = WMCreateArray(4);
177 plist->retainCount = 1;
179 if (!elem)
180 return plist;
182 WMAddToArray(plist->d.array, WMRetainPropList(elem));
184 va_start(ap, elem);
186 while (1) {
187 nelem = va_arg(ap, WMPropList*);
188 if(!nelem) {
189 va_end(ap);
190 return plist;
192 WMAddToArray(plist->d.array, WMRetainPropList(nelem));
197 WMPropList*
198 WMCreatePropListDictionaryFromEntries(WMPropList *key, WMPropList *value, ...)
203 WMPropList*
204 WMRetainPropList(WMPropList *plist)
206 WMPropList *key, *value;
207 WMHashEnumerator e;
208 int i;
210 plist->retainCount++;
212 switch(plist->type) {
213 case WPLString:
214 case WPLData:
215 break;
216 case WPLArray:
217 for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
218 WMRetainPropList(WMGetFromArray(plist->d.array, i));
220 break;
221 case WPLDictionary:
222 e = WMEnumerateHashTable(plist->d.dict);
223 while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
224 WMRetainPropList(key);
225 WMRetainPropList(value);
227 break;
228 default:
229 wwarning(_("Used proplist functions on non-WMPropLists objects"));
230 wassertrv(False, NULL);
233 return plist;
237 #if 0
238 void
239 WMReleasePropList(WMPropList *plist)
241 WMPropList *key, *value;
242 WMHashEnumerator e;
243 int i;
245 plist->retainCount--;
247 switch(plist->type) {
248 case WPLString:
249 if (plist->retainCount < 1) {
250 wfree(plist->d.string);
251 wfree(plist);
253 break;
254 case WPLData:
255 if (plist->retainCount < 1) {
256 WMReleaseData(plist->d.data);
257 wfree(plist);
259 break;
260 case WPLArray:
261 for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
262 WMReleasePropList(WMGetFromArray(plist->d.array, i));
264 if (plist->retainCount < 1) {
265 WMFreeArray(plist->d.array);
266 wfree(plist);
268 break;
269 case WPLDictionary:
270 e = WMEnumerateHashTable(plist->d.dict);
271 while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
272 WMReleasePropList(key);
273 WMReleasePropList(value);
275 if (plist->retainCount < 1) {
276 WMFreeHashTable(plist->d.dict);
277 wfree(plist);
279 break;
280 default:
281 wwarning(_("Used proplist functions on non-WMPropLists objects"));
282 wassertr(False);
285 #else
287 void
288 WMReleasePropList(WMPropList *plist)
290 WMPropList *key, *value;
291 WMHashEnumerator e;
292 int i;
294 plist->retainCount--;
296 switch(plist->type) {
297 case WPLString:
298 case WPLData:
299 break;
300 case WPLArray:
301 for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
302 WMReleasePropList(WMGetFromArray(plist->d.array, i));
304 break;
305 case WPLDictionary:
306 e = WMEnumerateHashTable(plist->d.dict);
307 while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
308 WMReleasePropList(key);
309 WMReleasePropList(value);
311 break;
312 default:
313 wwarning(_("Used proplist functions on non-WMPropLists objects"));
314 wassertr(False);
317 if (plist->retainCount > 0)
318 return;
320 switch(plist->type) {
321 case WPLString:
322 wfree(plist->d.string);
323 break;
324 case WPLData:
325 WMReleaseData(plist->d.data);
326 break;
327 case WPLArray:
328 WMFreeArray(plist->d.array);
329 break;
330 case WPLDictionary:
331 WMFreeHashTable(plist->d.dict);
332 break;
333 default:
334 wwarning(_("Used proplist functions on non-WMPropLists objects"));
335 wassertr(False);
337 wfree(plist);
339 #endif
342 Bool
343 WMPropListIsString(WMPropList *plist)
345 return (plist->type == WPLString);
349 Bool
350 WMPropListIsData(WMPropList *plist)
352 return (plist->type == WPLData);
356 Bool
357 WMPropListIsArray(WMPropList *plist)
359 return (plist->type == WPLArray);
363 Bool
364 WMPropListIsDictionary(WMPropList *plist)
366 return (plist->type == WPLDictionary);
370 Bool
371 WMPropListIsSimple(WMPropList *plist)
373 return (plist->type==WPLString || plist->type==WPLData);
377 Bool
378 WMPropListIsCompound(WMPropList *plist)
380 return (plist->type==WPLArray || plist->type==WPLDictionary);
384 Bool
385 WMArePropListsEqual(WMPropList *plist, WMPropList *other)
387 WMPropList *key1, *key2, *item1, *item2;
388 WMHashEnumerator enumerator;
389 int n, i;
391 if (plist->type != other->type)
392 return False;
394 switch(plist->type) {
395 case WPLString:
396 return ((*strCmp)(plist->d.string, other->d.string) == 0);
397 case WPLData:
398 return WMIsDataEqualToData(plist->d.data, other->d.data);
399 case WPLArray:
400 n = WMGetArrayItemCount(plist->d.array);
401 if (n != WMGetArrayItemCount(other->d.array))
402 return False;
403 for (i=0; i<n; i++) {
404 item1 = WMGetFromArray(plist->d.array, i);
405 item2 = WMGetFromArray(other->d.array, i);
406 if (!WMArePropListsEqual(item1, item2))
407 return False;
409 return True;
410 case WPLDictionary:
411 if (WMCountHashTable(plist->d.dict) != WMCountHashTable(other->d.dict))
412 return False;
413 enumerator = WMEnumerateHashTable(plist->d.dict);
414 while (WMNextHashEnumeratorItemAndKey(&enumerator, (void**)&item1,
415 (void**)&key1)) {
416 item2 = WMHashGet(other->d.dict, key1);
417 if (!item2 || !item1 || !WMArePropListsEqual(item1, item2))
418 return False;
420 return True;
421 default:
422 wwarning(_("Used proplist functions on non-WMPropLists objects"));
423 wassertrv(False, False);
426 return False;