18
WPLString = 0x57504c01,
20
WPLArray = 0x57504c03,
21
WPLDictionary = 0x57504c04
25
typedef struct W_PropList {
39
typedef struct PLData {
47
typedef struct StringBuffer {
53
static unsigned hashPropList(WMPropList *plist);
54
static WMPropList* getPLString(PLData *pldata);
55
static WMPropList* getPLQString(PLData *pldata);
56
static WMPropList* getPLData(PLData *pldata);
57
static WMPropList* getPLArray(PLData *pldata);
58
static WMPropList* getPLDictionary(PLData *pldata);
59
static WMPropList* getPropList(PLData *pldata);
63
typedef unsigned (*hashFunc)(const void*);
64
typedef Bool (*isEqualFunc)(const void*, const void*);
65
typedef void* (*retainFunc)(const void*);
66
typedef void (*releaseFunc)(const void*);
68
static const WMHashTableCallbacks WMPropListHashCallbacks = {
69
(hashFunc)hashPropList,
70
(isEqualFunc)WMIsPropListEqualTo,
77
static Bool caseSensitive = True;
81
#define BUFFERSIZE 8192
82
#define BUFFERSIZE_INCREMENT 1024
86
# define DPUT(s) puts(s)
91
#define COMPLAIN(pld, msg) wwarning(_("syntax error in %s %s, line %i: %s"),\
92
(pld)->filename ? "file" : "PropList",\
93
(pld)->filename ? (pld)->filename : "description",\
94
(pld)->lineNumber, msg)
96
#define ISSTRINGABLE(c) (isalnum(c) || (c)=='.' || (c)=='_' || (c)=='/' \
99
#define CHECK_BUFFER_SIZE(buf, ptr) \
100
if ((ptr) >= (buf).size-1) {\
101
(buf).size += BUFFERSIZE_INCREMENT;\
102
(buf).str = wrealloc((buf).str, (buf).size);\
106
#define inrange(ch, min, max) ((ch)>=(min) && (ch)<=(max))
107
#define noquote(ch) (inrange(ch, 'a', 'z') || inrange(ch, 'A', 'Z') || inrange(ch, '0', '9') || ((ch)=='_') || ((ch)=='.') || ((ch)=='$'))
108
#define charesc(ch) (inrange(ch, 0x07, 0x0c) || ((ch)=='"') || ((ch)=='\\'))
109
#define numesc(ch) (((ch)<=0x06) || inrange(ch, 0x0d, 0x1f) || ((ch)>0x7e))
110
#define ishexdigit(ch) (inrange(ch, 'a', 'f') || inrange(ch, 'A', 'F') || inrange(ch, '0', '9'))
111
#define char2num(ch) (inrange(ch,'0','9') ? ((ch)-'0') : (inrange(ch,'a','f') ? ((ch)-0x57) : ((ch)-0x37)))
112
#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57))
116
#define MaxHashLength 64
119
hashPropList(WMPropList *plist)
126
switch (plist->type) {
128
key = plist->d.string;
129
len = WMIN(strlen(key), MaxHashLength);
130
for (i=0; i<len; i++) {
131
ret ^= tolower(key[i]) << ctr;
132
ctr = (ctr + 1) % sizeof (char *);
135
ret ^= tolower(*key++) << ctr;
136
ctr = (ctr + 1) % sizeof (char *);
141
key = WMDataBytes(plist->d.data);
142
len = WMIN(WMGetDataLength(plist->d.data), MaxHashLength);
143
for (i=0; i<len; i++) {
144
ret ^= key[i] << ctr;
145
ctr = (ctr + 1) % sizeof (char *);
150
wwarning(_("Only string or data is supported for a proplist dictionary key"));
159
retainPropListByCount(WMPropList *plist, int count)
161
WMPropList *key, *value;
165
plist->retainCount += count;
167
switch(plist->type) {
172
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
173
retainPropListByCount(WMGetFromArray(plist->d.array, i), count);
177
e = WMEnumerateHashTable(plist->d.dict);
178
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
179
retainPropListByCount(key, count);
180
retainPropListByCount(value, count);
184
wwarning(_("Used proplist functions on non-WMPropLists objects"));
185
wassertrv(False, NULL);
194
releasePropListByCount(WMPropList *plist, int count)
196
WMPropList *key, *value;
200
plist->retainCount -= count;
202
switch(plist->type) {
204
if (plist->retainCount < 1) {
205
wfree(plist->d.string);
210
if (plist->retainCount < 1) {
211
WMReleaseData(plist->d.data);
216
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
217
releasePropListByCount(WMGetFromArray(plist->d.array, i), count);
219
if (plist->retainCount < 1) {
220
WMFreeArray(plist->d.array);
225
e = WMEnumerateHashTable(plist->d.dict);
226
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
227
releasePropListByCount(key, count);
228
releasePropListByCount(value, count);
230
if (plist->retainCount < 1) {
231
WMFreeHashTable(plist->d.dict);
236
wwarning(_("Used proplist functions on non-WMPropLists objects"));
244
dataDescription(WMPropList *plist)
246
const unsigned char *data;
250
data = WMDataBytes(plist->d.data);
251
length = WMGetDataLength(plist->d.data);
253
retVal = (char*)wmalloc(2*length+length/4+3);
256
for (i=0, j=1; i<length; i++) {
257
retVal[j++] = num2char((data[i]>>4) & 0x0f);
258
retVal[j++] = num2char(data[i] & 0x0f);
259
if ((i & 0x03)==3 && i!=length-1) {
260
/* if we've just finished a 32-bit int, add a space */
272
stringDescription(WMPropList *plist)
275
char *retVal, *sPtr, *dPtr;
279
str = plist->d.string;
281
if (strlen(str) == 0) {
282
return wstrdup("\"\"");
285
/* FIXME: make this work with unichars. */
290
while ((ch = *sPtr)) {
305
retVal = (char*)wmalloc(len+1);
313
while ((ch = *sPtr)) {
317
case '\a': *dPtr = 'a'; break;
318
case '\b': *dPtr = 'b'; break;
319
case '\t': *dPtr = 't'; break;
320
case '\n': *dPtr = 'n'; break;
321
case '\v': *dPtr = 'v'; break;
322
case '\f': *dPtr = 'f'; break;
323
default: *dPtr = ch; /* " or \ */
325
} else if (numesc(ch)) {
327
*(dPtr++) = '0' + ((ch>>6)&07);
328
*(dPtr++) = '0' + ((ch>>3)&07);
329
*dPtr = '0' + (ch&07);
347
description(WMPropList *plist)
349
WMPropList *key, *val;
351
char *str, *tmp, *skey, *sval;
355
switch (plist->type) {
357
retstr = stringDescription(plist);
360
retstr = dataDescription(plist);
363
retstr = wstrdup("(");
364
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
365
str = description(WMGetFromArray(plist->d.array, i));
367
retstr = wstrappend(retstr, str);
369
tmp = (char *)wmalloc(strlen(retstr)+strlen(str)+3);
370
sprintf(tmp, "%s, %s", retstr, str);
376
retstr = wstrappend(retstr, ")");
379
retstr = wstrdup("{");
380
e = WMEnumerateHashTable(plist->d.dict);
381
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&val, (void**)&key)) {
382
skey = description(key);
383
sval = description(val);
384
tmp = (char*)wmalloc(strlen(retstr)+strlen(skey)+strlen(sval)+5);
385
sprintf(tmp, "%s%s = %s;", retstr, skey, sval);
391
retstr = wstrappend(retstr, "}");
394
wwarning(_("Used proplist functions on non-WMPropLists objects"));
395
wassertrv(False, NULL);
404
indentedDescription(WMPropList *plist, int level)
406
WMPropList *key, *val;
408
char *str, *tmp, *skey, *sval;
412
if (plist->type==WPLArray/* || plist->type==WPLDictionary*/) {
413
retstr = description(plist);
415
if (retstr && ((2*(level+1) + strlen(retstr)) <= 77)) {
423
switch (plist->type) {
425
retstr = stringDescription(plist);
428
retstr = dataDescription(plist);
431
retstr = wstrdup("(\n");
432
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
433
str = indentedDescription(WMGetFromArray(plist->d.array, i),
436
tmp = (char*)wmalloc(2*(level+1)+strlen(retstr)+strlen(str)+1);
437
sprintf(tmp, "%s%*s%s", retstr, 2*(level+1), "", str);
441
tmp = (char*)wmalloc(2*(level+1)+strlen(retstr)+strlen(str)+3);
442
sprintf(tmp, "%s,\n%*s%s", retstr, 2*(level+1), "", str);
448
tmp = (char*)wmalloc(strlen(retstr) + 2*level + 3);
449
sprintf(tmp, "%s\n%*s)", retstr, 2*level, "");
454
retstr = wstrdup("{\n");
455
e = WMEnumerateHashTable(plist->d.dict);
456
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&val, (void**)&key)) {
457
skey = indentedDescription(key, level+1);
458
sval = indentedDescription(val, level+1);
459
tmp = (char*)wmalloc(2*(level+1) + strlen(retstr) + strlen(skey)
461
sprintf(tmp, "%s%*s%s = %s;\n", retstr, 2*(level+1), "",
468
tmp = (char*)wmalloc(strlen(retstr) + 2*level + 2);
469
sprintf(tmp, "%s%*s}", retstr, 2*level, "");
474
wwarning(_("Used proplist functions on non-WMPropLists objects"));
475
wassertrv(False, NULL);
484
getChar(PLData *pldata)
488
c = pldata->ptr[pldata->pos];
496
pldata->lineNumber++;
503
getNonSpaceChar(PLData *pldata)
508
c = pldata->ptr[pldata->pos];
514
pldata->lineNumber++;
515
} else if (!isspace(c)) {
525
unescapestr(char *src)
527
char *dest = wmalloc(strlen(src)+1);
532
for (sPtr=src, dPtr=dest; *sPtr; sPtr++, dPtr++) {
537
if((ch>='0') && (ch<='3')) {
538
/* assume next 2 chars are octal too */
539
*dPtr = ((ch & 07) << 6);
540
*dPtr |= ((*(++sPtr)&07)<<3);
541
*dPtr |= *(++sPtr)&07;
544
case 'a' : *dPtr = '\a'; break;
545
case 'b' : *dPtr = '\b'; break;
546
case 't' : *dPtr = '\t'; break;
547
case 'r' : *dPtr = '\r'; break;
548
case 'n' : *dPtr = '\n'; break;
549
case 'v' : *dPtr = '\v'; break;
550
case 'f' : *dPtr = '\f'; break;
551
default : *dPtr = *sPtr;
564
getPLString(PLData *pldata)
571
sBuf.str = wmalloc(BUFFERSIZE);
572
sBuf.size = BUFFERSIZE;
576
if (ISSTRINGABLE(c)) {
577
CHECK_BUFFER_SIZE(sBuf, ptr);
592
char *tmp = unescapestr(sBuf.str);
593
plist = WMCreatePLString(tmp);
604
getPLQString(PLData *pldata)
607
int ptr = 0, escaping = 0, ok = 1;
611
sBuf.str = wmalloc(BUFFERSIZE);
612
sBuf.size = BUFFERSIZE;
620
} else if (c == '"') {
624
CHECK_BUFFER_SIZE(sBuf, ptr);
625
sBuf.str[ptr++] = '\\';
630
COMPLAIN(pldata, _("unterminated PropList string"));
634
CHECK_BUFFER_SIZE(sBuf, ptr);
644
char *tmp = unescapestr(sBuf.str);
645
plist = WMCreatePLString(tmp);
656
getPLData(PLData *pldata)
661
unsigned char buf[BUFFERSIZE], byte;
665
data = WMCreateDataWithCapacity(0);
668
c1 = getNonSpaceChar(pldata);
670
COMPLAIN(pldata, _("unterminated PropList data"));
673
} else if (c1=='>') {
675
} else if (ishexdigit(c1)) {
676
c2 = getNonSpaceChar(pldata);
677
if (c2==0 || c2=='>') {
678
COMPLAIN(pldata, _("unterminated PropList data (missing hexdigit)"));
681
} else if (ishexdigit(c2)) {
682
byte = char2num(c1) << 4;
683
byte |= char2num(c2);
685
if (len == sizeof(buf)) {
686
WMAppendDataBytes(data, buf, len);
690
COMPLAIN(pldata, _("non hexdigit character in PropList data"));
695
COMPLAIN(pldata, _("non hexdigit character in PropList data"));
707
WMAppendDataBytes(data, buf, len);
709
plist = WMCreatePLData(data);
717
getPLArray(PLData *pldata)
722
WMPropList *array, *obj;
724
array = WMCreatePLArray(NULL);
727
c = getNonSpaceChar(pldata);
729
COMPLAIN(pldata, _("unterminated PropList array"));
732
} else if (c == ')') {
734
} else if (c == ',') {
735
/* continue normally */
737
COMPLAIN(pldata, _("missing or unterminated PropList array"));
745
obj = getPropList(pldata);
747
COMPLAIN(pldata, _("could not get PropList array element"));
751
WMAddToPLArray(array, obj);
752
WMReleasePropList(obj);
756
WMReleasePropList(array);
765
getPLDictionary(PLData *pldata)
769
WMPropList *dict, *key, *value;
771
dict = WMCreatePLDictionary(NULL, NULL);
774
c = getNonSpaceChar(pldata);
776
COMPLAIN(pldata, _("unterminated PropList dictionary"));
783
DPUT("getting PropList dictionary key");
785
key = getPLData(pldata);
786
} else if (c == '"') {
787
key = getPLQString(pldata);
788
} else if (ISSTRINGABLE(c)) {
790
key = getPLString(pldata);
793
COMPLAIN(pldata, _("missing PropList dictionary key"));
795
COMPLAIN(pldata, _("missing PropList dictionary entry key "
796
"or unterminated dictionary"));
803
COMPLAIN(pldata, _("error parsing PropList dictionary key"));
808
c = getNonSpaceChar(pldata);
810
WMReleasePropList(key);
811
COMPLAIN(pldata, _("missing = in PropList dictionary entry"));
816
DPUT("getting PropList dictionary entry value for key");
817
value = getPropList(pldata);
819
COMPLAIN(pldata, _("error parsing PropList dictionary entry value"));
820
WMReleasePropList(key);
825
c = getNonSpaceChar(pldata);
827
COMPLAIN(pldata, _("missing ; in PropList dictionary entry"));
828
WMReleasePropList(key);
829
WMReleasePropList(value);
834
WMPutInPLDictionary(dict, key, value);
835
WMReleasePropList(key);
836
WMReleasePropList(value);
840
WMReleasePropList(dict);
849
getPropList(PLData *pldata)
854
c = getNonSpaceChar(pldata);
858
DPUT("End of PropList");
863
DPUT("Getting PropList dictionary");
864
plist = getPLDictionary(pldata);
868
DPUT("Getting PropList array");
869
plist = getPLArray(pldata);
873
DPUT("Getting PropList data");
874
plist = getPLData(pldata);
878
DPUT("Getting PropList quoted string");
879
plist = getPLQString(pldata);
883
if (ISSTRINGABLE(c)) {
884
DPUT("Getting PropList string");
886
plist = getPLString(pldata);
888
COMPLAIN(pldata, _("was expecting a string, data, array or "
889
"dictionary. If it's a string, try enclosing "
891
if (c=='#' || c=='/') {
892
wwarning(_("Comments are not allowed inside WindowMaker owned"
905
WMPLSetCaseSensitive(Bool caseSensitiveness)
907
caseSensitive = caseSensitiveness;
912
WMCreatePLString(char *str)
916
wassertrv(str!=NULL, NULL);
918
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
920
plist->type = WPLString;
921
plist->d.string = wstrdup(str);
922
plist->retainCount = 1;
929
WMCreatePLData(WMData *data)
933
wassertrv(data!=NULL, NULL);
935
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
937
plist->type = WPLData;
938
plist->d.data = WMRetainData(data);
939
plist->retainCount = 1;
946
WMCreatePLDataWithBytes(unsigned char *bytes, unsigned int length)
950
wassertrv(bytes!=NULL, NULL);
952
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
954
plist->type = WPLData;
955
plist->d.data = WMCreateDataWithBytes(bytes, length);
956
plist->retainCount = 1;
963
WMCreatePLDataWithBytesNoCopy(unsigned char *bytes, unsigned int length,
964
WMFreeDataProc *destructor)
968
wassertrv(bytes!=NULL, NULL);
970
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
972
plist->type = WPLData;
973
plist->d.data = WMCreateDataWithBytesNoCopy(bytes, length, destructor);
974
plist->retainCount = 1;
981
WMCreatePLArray(WMPropList *elem, ...)
983
WMPropList *plist, *nelem;
986
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
987
plist->type = WPLArray;
988
plist->d.array = WMCreateArray(4);
989
plist->retainCount = 1;
994
WMAddToArray(plist->d.array, WMRetainPropList(elem));
999
nelem = va_arg(ap, WMPropList*);
1004
WMAddToArray(plist->d.array, WMRetainPropList(nelem));
1010
WMCreatePLDictionary(WMPropList *key, WMPropList *value, ...)
1012
WMPropList *plist, *nkey, *nvalue, *k, *v;
1015
plist = (WMPropList*)wmalloc(sizeof(W_PropList));
1016
plist->type = WPLDictionary;
1017
plist->d.dict = WMCreateHashTable(WMPropListHashCallbacks);
1018
plist->retainCount = 1;
1023
WMHashInsert(plist->d.dict, WMRetainPropList(key), WMRetainPropList(value));
1025
va_start(ap, value);
1028
nkey = va_arg(ap, WMPropList*);
1033
nvalue = va_arg(ap, WMPropList*);
1038
if (WMHashGetItemAndKey(plist->d.dict, nkey, (void**)&v, (void**)&k)) {
1039
WMHashRemove(plist->d.dict, k);
1040
WMReleasePropList(k);
1041
WMReleasePropList(v);
1043
WMHashInsert(plist->d.dict, WMRetainPropList(nkey),
1044
WMRetainPropList(nvalue));
1050
WMRetainPropList(WMPropList *plist)
1052
WMPropList *key, *value;
1056
plist->retainCount++;
1058
switch(plist->type) {
1063
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
1064
WMRetainPropList(WMGetFromArray(plist->d.array, i));
1068
e = WMEnumerateHashTable(plist->d.dict);
1069
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
1070
WMRetainPropList(key);
1071
WMRetainPropList(value);
1075
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1076
wassertrv(False, NULL);
1085
WMReleasePropList(WMPropList *plist)
1087
WMPropList *key, *value;
1091
plist->retainCount--;
1093
switch(plist->type) {
1095
if (plist->retainCount < 1) {
1096
wfree(plist->d.string);
1101
if (plist->retainCount < 1) {
1102
WMReleaseData(plist->d.data);
1107
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
1108
WMReleasePropList(WMGetFromArray(plist->d.array, i));
1110
if (plist->retainCount < 1) {
1111
WMFreeArray(plist->d.array);
1116
e = WMEnumerateHashTable(plist->d.dict);
1117
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
1118
WMReleasePropList(key);
1119
WMReleasePropList(value);
1121
if (plist->retainCount < 1) {
1122
WMFreeHashTable(plist->d.dict);
1127
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1135
WMInsertInPLArray(WMPropList *plist, int index, WMPropList *item)
1137
wassertr(plist->type==WPLArray);
1139
retainPropListByCount(item, plist->retainCount);
1140
WMInsertInArray(plist->d.array, index, item);
1145
WMAddToPLArray(WMPropList *plist, WMPropList *item)
1147
wassertr(plist->type==WPLArray);
1149
retainPropListByCount(item, plist->retainCount);
1150
WMAddToArray(plist->d.array, item);
1155
WMDeleteFromPLArray(WMPropList *plist, int index)
1159
wassertr(plist->type==WPLArray);
1161
item = WMGetFromArray(plist->d.array, index);
1163
WMDeleteFromArray(plist->d.array, index);
1164
releasePropListByCount(item, plist->retainCount);
1170
WMRemoveFromPLArray(WMPropList *plist, WMPropList *item)
1175
wassertr(plist->type==WPLArray);
1177
for (i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
1178
iPtr = WMGetFromArray(plist->d.array, i);
1179
if (WMIsPropListEqualTo(item, iPtr)) {
1180
WMDeleteFromArray(plist->d.array, i);
1181
releasePropListByCount(iPtr, plist->retainCount);
1189
WMPutInPLDictionary(WMPropList *plist, WMPropList *key, WMPropList *value)
1191
wassertr(plist->type==WPLDictionary);
1193
/*WMRetainPropList(key);*/
1194
WMRemoveFromPLDictionary(plist, key);
1195
retainPropListByCount(key, plist->retainCount);
1196
retainPropListByCount(value, plist->retainCount);
1197
WMHashInsert(plist->d.dict, key, value);
1198
/*WMReleasePropList(key);*/
1203
WMRemoveFromPLDictionary(WMPropList *plist, WMPropList *key)
1207
wassertr(plist->type==WPLDictionary);
1209
if (WMHashGetItemAndKey(plist->d.dict, key, (void**)&v, (void**)&k)) {
1210
WMHashRemove(plist->d.dict, k);
1211
releasePropListByCount(k, plist->retainCount);
1212
releasePropListByCount(v, plist->retainCount);
1218
WMMergePLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive)
1220
WMPropList *key, *value, *dvalue;
1223
wassertr(source->type==WPLDictionary && dest->type==WPLDictionary);
1228
e = WMEnumerateHashTable(source->d.dict);
1229
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
1230
if (recursive && value->type==WPLDictionary) {
1231
dvalue = WMHashGet(dest->d.dict, key);
1232
if (dvalue && dvalue->type==WPLDictionary) {
1233
WMMergePLDictionaries(dvalue, value, True);
1235
WMPutInPLDictionary(dest, key, value);
1238
WMPutInPLDictionary(dest, key, value);
1247
WMSubtractPLDictionaries(WMPropList *dest, WMPropList *source, Bool recursive)
1249
WMPropList *key, *value, *dvalue;
1252
wassertr(source->type==WPLDictionary && dest->type==WPLDictionary);
1254
if (source == dest) {
1255
WMPropList *keys = WMGetPLDictionaryKeys(dest);
1258
for (i=0; i<WMGetArrayItemCount(keys->d.array); i++) {
1259
WMRemoveFromPLDictionary(dest, WMGetFromArray(keys->d.array, i));
1264
e = WMEnumerateHashTable(source->d.dict);
1265
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&value, (void**)&key)) {
1266
dvalue = WMHashGet(dest->d.dict, key);
1269
if (WMIsPropListEqualTo(value, dvalue)) {
1270
WMRemoveFromPLDictionary(dest, key);
1271
} else if (recursive && value->type==WPLDictionary &&
1272
dvalue->type==WPLDictionary) {
1273
WMSubtractPLDictionaries(dvalue, value, True);
1282
WMGetPropListItemCount(WMPropList *plist)
1284
switch(plist->type) {
1287
return 0; /* should this be 1 instead? */
1289
return WMGetArrayItemCount(plist->d.array);
1291
return (int)WMCountHashTable(plist->d.dict);
1293
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1294
wassertrv(False, 0);
1303
WMIsPLString(WMPropList *plist)
1305
return (plist->type == WPLString);
1310
WMIsPLData(WMPropList *plist)
1312
return (plist->type == WPLData);
1317
WMIsPLArray(WMPropList *plist)
1319
return (plist->type == WPLArray);
1324
WMIsPLDictionary(WMPropList *plist)
1326
return (plist->type == WPLDictionary);
1331
WMIsPropListEqualTo(WMPropList *plist, WMPropList *other)
1333
WMPropList *key1, *item1, *item2;
1334
WMHashEnumerator enumerator;
1337
if (plist->type != other->type)
1340
switch(plist->type) {
1342
if (caseSensitive) {
1343
return (strcmp(plist->d.string, other->d.string) == 0);
1345
return (strcasecmp(plist->d.string, other->d.string) == 0);
1348
return WMIsDataEqualToData(plist->d.data, other->d.data);
1350
n = WMGetArrayItemCount(plist->d.array);
1351
if (n != WMGetArrayItemCount(other->d.array))
1353
for (i=0; i<n; i++) {
1354
item1 = WMGetFromArray(plist->d.array, i);
1355
item2 = WMGetFromArray(other->d.array, i);
1356
if (!WMIsPropListEqualTo(item1, item2))
1361
if (WMCountHashTable(plist->d.dict) != WMCountHashTable(other->d.dict))
1363
enumerator = WMEnumerateHashTable(plist->d.dict);
1364
while (WMNextHashEnumeratorItemAndKey(&enumerator, (void**)&item1,
1366
item2 = WMHashGet(other->d.dict, key1);
1367
if (!item2 || !item1 || !WMIsPropListEqualTo(item1, item2))
1372
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1373
wassertrv(False, False);
1382
WMGetFromPLString(WMPropList *plist)
1384
wassertrv(plist->type==WPLString, NULL);
1386
return plist->d.string;
1391
WMGetFromPLData(WMPropList *plist)
1393
wassertrv(plist->type==WPLData, NULL);
1395
return plist->d.data;
1399
const unsigned char*
1400
WMGetPLDataBytes(WMPropList *plist)
1402
wassertrv(plist->type==WPLData, NULL);
1404
return WMDataBytes(plist->d.data);
1409
WMGetPLDataLength(WMPropList *plist)
1411
wassertrv(plist->type==WPLData, 0);
1413
return WMGetDataLength(plist->d.data);
1418
WMGetFromPLArray(WMPropList *plist, int index)
1420
wassertrv(plist->type==WPLArray, NULL);
1422
return WMGetFromArray(plist->d.array, index);
1427
WMGetFromPLDictionary(WMPropList *plist, WMPropList *key)
1429
wassertrv(plist->type==WPLDictionary, NULL);
1431
return WMHashGet(plist->d.dict, key);
1436
WMGetPLDictionaryKeys(WMPropList *plist)
1438
WMPropList *array, *key;
1439
WMHashEnumerator enumerator;
1441
wassertrv(plist->type==WPLDictionary, NULL);
1443
array = (WMPropList*)wmalloc(sizeof(W_PropList));
1444
array->type = WPLArray;
1445
array->d.array = WMCreateArray(WMCountHashTable(plist->d.dict));
1446
array->retainCount = 1;
1448
enumerator = WMEnumerateHashTable(plist->d.dict);
1449
while ((key = WMNextHashEnumeratorKey(&enumerator))) {
1450
WMAddToArray(array->d.array, WMRetainPropList(key));
1458
WMShallowCopyPropList(WMPropList *plist)
1460
WMPropList *ret = NULL;
1461
WMPropList *key, *item;
1466
switch(plist->type) {
1468
ret = WMCreatePLString(plist->d.string);
1471
data = WMCreateDataWithData(plist->d.data);
1472
ret = WMCreatePLData(data);
1473
WMReleaseData(data);
1476
ret = (WMPropList*)wmalloc(sizeof(W_PropList));
1477
ret->type = WPLArray;
1478
ret->d.array = WMCreateArrayWithArray(plist->d.array);
1479
ret->retainCount = 1;
1481
for(i=0; i<WMGetArrayItemCount(ret->d.array); i++)
1482
WMRetainPropList(WMGetFromArray(ret->d.array, i));
1486
ret = WMCreatePLDictionary(NULL, NULL);
1487
e = WMEnumerateHashTable(plist->d.dict);
1488
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&item, (void**)&key)) {
1489
WMPutInPLDictionary(ret, key, item);
1493
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1494
wassertrv(False, NULL);
1503
WMDeepCopyPropList(WMPropList *plist)
1505
WMPropList *ret = NULL;
1506
WMPropList *key, *item;
1511
switch(plist->type) {
1513
ret = WMCreatePLString(plist->d.string);
1516
data = WMCreateDataWithData(plist->d.data);
1517
ret = WMCreatePLData(data);
1518
WMReleaseData(data);
1521
ret = WMCreatePLArray(NULL);
1522
for(i=0; i<WMGetArrayItemCount(plist->d.array); i++) {
1523
item = WMDeepCopyPropList(WMGetFromArray(plist->d.array, i));
1524
WMAddToArray(ret->d.array, item);
1528
ret = WMCreatePLDictionary(NULL, NULL);
1529
e = WMEnumerateHashTable(plist->d.dict);
1530
/* While we copy an existing dictionary there is no way that we can
1531
* have duplicate keys, so we don't need to first remove a key/value
1532
* pair before inserting the new key/value.
1534
while (WMNextHashEnumeratorItemAndKey(&e, (void**)&item, (void**)&key)) {
1535
WMHashInsert(ret->d.dict, WMDeepCopyPropList(key),
1536
WMDeepCopyPropList(item));
1540
wwarning(_("Used proplist functions on non-WMPropLists objects"));
1541
wassertrv(False, NULL);
1550
WMCreatePropListFromDescription(char *desc)
1552
WMPropList *plist = NULL;
1555
pldata = (PLData*) wmalloc(sizeof(PLData));
1556
memset(pldata, 0, sizeof(PLData));
1558
pldata->lineNumber = 1;
1560
plist = getPropList(pldata);
1562
if (getNonSpaceChar(pldata)!=0 && plist) {
1563
COMPLAIN(pldata, _("extra data after end of property list"));
1565
* We can't just ignore garbage after the end of the description
1566
* (especially if the description was read from a file), because
1567
* the "garbage" can be the real data and the real garbage is in
1568
* fact in the beginning of the file (which is now inside plist)
1570
WMReleasePropList(plist);
1581
WMGetPropListDescription(WMPropList *plist, Bool indented)
1583
return (indented ? indentedDescription(plist, 0) : description(plist));
1588
WMReadPropListFromFile(char *file)
1590
WMPropList *plist = NULL;
1596
f = fopen(file, "rb");
1598
/* let the user print the error message if he really needs to */
1599
/*wsyserror(_("could not open domain file '%s' for reading"), file);*/
1603
if (stat(file, &stbuf)==0) {
1604
length = (size_t) stbuf.st_size;
1606
wsyserror(_("could not get size for file '%s'"), file);
1611
pldata = (PLData*) wmalloc(sizeof(PLData));
1612
memset(pldata, 0, sizeof(PLData));
1613
pldata->ptr = (char*) wmalloc(length+1);
1614
pldata->filename = file;
1615
pldata->lineNumber = 1;
1617
if (fread(pldata->ptr, length, 1, f) != 1) {
1619
wsyserror(_("error reading from file '%s'"), file);
1625
pldata->ptr[length] = 0;
1627
plist = getPropList(pldata);
1629
if (getNonSpaceChar(pldata)!=0 && plist) {
1630
COMPLAIN(pldata, _("extra data after end of property list"));
1632
* We can't just ignore garbage after the end of the description
1633
* (especially if the description was read from a file), because
1634
* the "garbage" can be the real data and the real garbage is in
1635
* fact in the beginning of the file (which is now inside plist)
1637
WMReleasePropList(plist);
1650
/* TODO: review this function's code */
1653
WMWritePropListToFile(WMPropList *plist, char *path, Bool atomically)
1664
/* Use the path name of the destination file as a prefix for the
1665
* mkstemp() call so that we can be sure that both files are on
1666
* the same filesystem and the subsequent rename() will work. */
1667
thePath = wstrconcat(path, ".XXXXXX");
1670
if ((fd = mkstemp(thePath)) < 0) {
1671
wsyserror(_("mkstemp (%s) failed"), thePath);
1676
fchmod(fd, 0644 & ~mask);
1677
if ((theFile = fdopen(fd, "wb")) == NULL) {
1681
if (mktemp(thePath) == NULL) {
1682
wsyserror(_("mktemp (%s) failed"), thePath);
1685
theFile = fopen(thePath, "wb");
1688
thePath = wstrdup(path);
1689
theFile = fopen(thePath, "wb");
1692
if (theFile == NULL) {
1693
wsyserror(_("open (%s) failed"), thePath);
1697
desc = indentedDescription(plist, 0);
1699
if (fprintf(theFile, "%s\n", desc) != strlen(desc)+1) {
1700
wsyserror(_("writing to file: %s failed"), thePath);
1707
if (fclose(theFile) != 0) {
1708
wsyserror(_("fclose (%s) failed"), thePath);
1712
/* If we used a temporary file, we still need to rename() it be the
1713
* real file. Also, we need to try to retain the file attributes of
1714
* the original file we are overwriting (if we are) */
1716
if (rename(thePath, path) != 0) {
1717
wsyserror(_("rename ('%s' to '%s') failed"), thePath, path);