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
)WMPLIsEqualToPL
,
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 switch (plist
->type
) {
414 retstr
= stringDescription(plist
);
417 retstr
= dataDescription(plist
);
420 retstr
= wstrdup("(\n");
421 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
422 str
= indentedDescription(WMGetFromArray(plist
->d
.array
, i
),
425 tmp
= (char*)wmalloc(2*(level
+1)+strlen(retstr
)+strlen(str
)+1);
426 sprintf(tmp
, "%s%*s%s", retstr
, 2*(level
+1), "", str
);
430 tmp
= (char*)wmalloc(2*(level
+1)+strlen(retstr
)+strlen(str
)+3);
431 sprintf(tmp
, "%s,\n%*s%s", retstr
, 2*(level
+1), "", str
);
437 tmp
= (char*)wmalloc(strlen(retstr
) + 2*level
+ 3);
438 sprintf(tmp
, "%s\n%*s)", retstr
, 2*level
, "");
443 retstr
= wstrdup("{\n");
444 e
= WMEnumerateHashTable(plist
->d
.dict
);
445 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&val
, (void**)&key
)) {
446 skey
= indentedDescription(key
, level
+1);
447 sval
= indentedDescription(val
, level
+1);
448 tmp
= (char*)wmalloc(2*(level
+1) + strlen(retstr
) + strlen(skey
)
450 sprintf(tmp
, "%s%*s%s = %s;\n", retstr
, 2*(level
+1), "",
457 tmp
= (char*)wmalloc(strlen(retstr
) + 2*level
+ 2);
458 sprintf(tmp
, "%s%*s}", retstr
, 2*level
, "");
463 wwarning(_("Used proplist functions on non-WMPropLists objects"));
464 wassertrv(False
, NULL
);
473 getChar(PLData
*pldata
)
477 c
= pldata
->ptr
[pldata
->pos
];
485 pldata
->lineNumber
++;
492 getNonSpaceChar(PLData
*pldata
)
497 c
= pldata
->ptr
[pldata
->pos
];
503 pldata
->lineNumber
++;
504 } else if (!isspace(c
)) {
514 unescapestr(char *src
)
516 char *dest
= wmalloc(strlen(src
)+1);
521 for (sPtr
=src
, dPtr
=dest
; *sPtr
; sPtr
++, dPtr
++) {
526 if((ch
>='0') && (ch
<='3')) {
527 /* assume next 2 chars are octal too */
528 *dPtr
= ((ch
& 07) << 6);
529 *dPtr
|= ((*(++sPtr
)&07)<<3);
530 *dPtr
|= *(++sPtr
)&07;
533 case 'a' : *dPtr
= '\a'; break;
534 case 'b' : *dPtr
= '\b'; break;
535 case 't' : *dPtr
= '\t'; break;
536 case 'r' : *dPtr
= '\r'; break;
537 case 'n' : *dPtr
= '\n'; break;
538 case 'v' : *dPtr
= '\v'; break;
539 case 'f' : *dPtr
= '\f'; break;
540 default : *dPtr
= *sPtr
;
553 getPLString(PLData
*pldata
)
560 sBuf
.str
= wmalloc(BUFFERSIZE
);
561 sBuf
.size
= BUFFERSIZE
;
565 if (ISSTRINGABLE(c
)) {
566 CHECK_BUFFER_SIZE(sBuf
, ptr
);
581 char *tmp
= unescapestr(sBuf
.str
);
582 plist
= WMPLCreateString(tmp
);
593 getPLQString(PLData
*pldata
)
596 int ptr
= 0, escaping
= 0, ok
= 1;
600 sBuf
.str
= wmalloc(BUFFERSIZE
);
601 sBuf
.size
= BUFFERSIZE
;
609 } else if (c
== '"') {
613 CHECK_BUFFER_SIZE(sBuf
, ptr
);
614 sBuf
.str
[ptr
++] = '\\';
619 COMPLAIN(pldata
, _("unterminated PropList string"));
623 CHECK_BUFFER_SIZE(sBuf
, ptr
);
633 char *tmp
= unescapestr(sBuf
.str
);
634 plist
= WMPLCreateString(tmp
);
645 getPLData(PLData
*pldata
)
650 unsigned char buf
[BUFFERSIZE
], byte
;
654 data
= WMCreateDataWithCapacity(0);
657 c1
= getNonSpaceChar(pldata
);
659 COMPLAIN(pldata
, _("unterminated PropList data"));
662 } else if (c1
=='>') {
664 } else if (ishexdigit(c1
)) {
665 c2
= getNonSpaceChar(pldata
);
666 if (c2
==0 || c2
=='>') {
667 COMPLAIN(pldata
, _("unterminated PropList data (missing hexdigit)"));
670 } else if (ishexdigit(c2
)) {
671 byte
= char2num(c1
) << 4;
672 byte
|= char2num(c2
);
674 if (len
== sizeof(buf
)) {
675 WMAppendDataBytes(data
, buf
, len
);
679 COMPLAIN(pldata
, _("non hexdigit character in PropList data"));
692 WMAppendDataBytes(data
, buf
, len
);
694 plist
= WMPLCreateData(data
);
702 getPLArray(PLData
*pldata
)
707 WMPropList
*array
, *obj
;
709 array
= WMPLCreateArray(NULL
);
712 c
= getNonSpaceChar(pldata
);
714 COMPLAIN(pldata
, _("unterminated PropList array"));
717 } else if (c
== ')') {
719 } else if (c
== ',') {
720 /* continue normally */
722 COMPLAIN(pldata
, _("missing , or unterminated PropList array"));
730 obj
= getPropList(pldata
);
732 COMPLAIN(pldata
, _("could not get PropList array element"));
736 WMPLAddToArray(array
, obj
);
750 getPLDictionary(PLData
*pldata
)
754 WMPropList
*dict
, *key
, *value
;
756 dict
= WMPLCreateDictionary(NULL
, NULL
);
759 c
= getNonSpaceChar(pldata
);
761 COMPLAIN(pldata
, _("unterminated PropList dictionary"));
768 DPUT("getting PropList dictionary key");
770 key
= getPLData(pldata
);
771 } else if (c
== '"') {
772 key
= getPLQString(pldata
);
773 } else if (ISSTRINGABLE(c
)) {
775 key
= getPLString(pldata
);
778 COMPLAIN(pldata
, _("missing PropList dictionary key"));
780 COMPLAIN(pldata
, _("missing PropList dictionary entry key "
781 "or unterminated dictionary"));
788 COMPLAIN(pldata
, _("error parsing PropList dictionary key"));
793 c
= getNonSpaceChar(pldata
);
796 COMPLAIN(pldata
, _("missing = in PropList dictionary entry"));
801 DPUT("getting PropList dictionary entry value for key");
802 value
= getPropList(pldata
);
804 COMPLAIN(pldata
, _("error parsing PropList dictionary entry value"));
810 c
= getNonSpaceChar(pldata
);
812 COMPLAIN(pldata
, _("missing ; in PropList dictionary entry"));
819 WMPLPutInDictionary(dict
, key
, value
);
834 getPropList(PLData
*pldata
)
839 c
= getNonSpaceChar(pldata
);
843 DPUT("End of PropList");
848 DPUT("Getting PropList dictionary");
849 plist
= getPLDictionary(pldata
);
853 DPUT("Getting PropList srrsy");
854 plist
= getPLArray(pldata
);
858 DPUT("Getting PropList data");
859 plist
= getPLData(pldata
);
863 DPUT("Getting PropList quoted string");
864 plist
= getPLQString(pldata
);
868 if (ISSTRINGABLE(c
)) {
869 DPUT("Getting PropList string");
871 plist
= getPLString(pldata
);
873 COMPLAIN(pldata
, _("was expecting a string, data, array or "
874 "dictionary. If it's a string, try enclosing "
876 if (c
=='#' || c
=='/') {
877 wwarning(_("Comments are not allowed inside WindowMaker owned"
890 WMPLSetCaseSensitive(Bool useCase
)
892 caseSensitive
= useCase
;
897 WMPLCreateString(char *str
)
901 wassertrv(str
!=NULL
, NULL
);
903 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
905 plist
->type
= WPLString
;
906 plist
->d
.string
= wstrdup(str
);
907 plist
->retainCount
= 1;
914 WMPLCreateData(WMData
*data
)
918 wassertrv(data
!=NULL
, NULL
);
920 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
922 plist
->type
= WPLData
;
923 plist
->d
.data
= WMRetainData(data
);
924 plist
->retainCount
= 1;
931 WMPLCreateDataWithBytes(unsigned char *bytes
, unsigned int length
)
935 wassertrv(bytes
!=NULL
, NULL
);
937 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
939 plist
->type
= WPLData
;
940 plist
->d
.data
= WMCreateDataWithBytes(bytes
, length
);
941 plist
->retainCount
= 1;
948 WMPLCreateDataWithBytesNoCopy(unsigned char *bytes
, unsigned int length
,
949 WMFreeDataProc
*destructor
)
953 wassertrv(bytes
!=NULL
, NULL
);
955 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
957 plist
->type
= WPLData
;
958 plist
->d
.data
= WMCreateDataWithBytesNoCopy(bytes
, length
, destructor
);
959 plist
->retainCount
= 1;
966 WMPLCreateArray(WMPropList
*elem
, ...)
968 WMPropList
*plist
, *nelem
;
971 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
972 plist
->type
= WPLArray
;
973 plist
->d
.array
= WMCreateArray(4);
974 plist
->retainCount
= 1;
979 WMAddToArray(plist
->d
.array
, WMPLRetain(elem
));
984 nelem
= va_arg(ap
, WMPropList
*);
989 WMAddToArray(plist
->d
.array
, WMPLRetain(nelem
));
995 WMPLCreateDictionary(WMPropList
*key
, WMPropList
*value
, ...)
997 WMPropList
*plist
, *nkey
, *nvalue
, *k
, *v
;
1000 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1001 plist
->type
= WPLDictionary
;
1002 plist
->d
.dict
= WMCreateHashTable(WMPropListHashCallbacks
);
1003 plist
->retainCount
= 1;
1008 WMHashInsert(plist
->d
.dict
, WMPLRetain(key
), WMPLRetain(value
));
1010 va_start(ap
, value
);
1013 nkey
= va_arg(ap
, WMPropList
*);
1018 nvalue
= va_arg(ap
, WMPropList
*);
1023 if (WMHashGetItemAndKey(plist
->d
.dict
, nkey
, (void**)&v
, (void**)&k
)) {
1024 WMHashRemove(plist
->d
.dict
, k
);
1028 WMHashInsert(plist
->d
.dict
, WMPLRetain(nkey
), WMPLRetain(nvalue
));
1034 WMPLInsertInArray(WMPropList
*plist
, int index
, WMPropList
*item
)
1036 wassertr(plist
->type
==WPLArray
);
1038 retainPropListByCount(item
, plist
->retainCount
);
1039 WMInsertInArray(plist
->d
.array
, index
, item
);
1044 WMPLAddToArray(WMPropList
*plist
, WMPropList
*item
)
1046 wassertr(plist
->type
==WPLArray
);
1048 retainPropListByCount(item
, plist
->retainCount
);
1049 WMAddToArray(plist
->d
.array
, item
);
1054 WMPLDeleteFromArray(WMPropList
*plist
, int index
)
1058 wassertr(plist
->type
==WPLArray
);
1060 item
= WMGetFromArray(plist
->d
.array
, index
);
1062 WMDeleteFromArray(plist
->d
.array
, index
);
1063 releasePropListByCount(item
, plist
->retainCount
);
1069 WMPLRemoveFromArray(WMPropList
*plist
, WMPropList
*item
)
1074 wassertr(plist
->type
==WPLArray
);
1076 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1077 iPtr
= WMGetFromArray(plist
->d
.array
, i
);
1078 if (WMPLIsEqualToPL(item
, iPtr
)) {
1079 WMDeleteFromArray(plist
->d
.array
, i
);
1080 releasePropListByCount(iPtr
, plist
->retainCount
);
1088 WMPLPutInDictionary(WMPropList
*plist
, WMPropList
*key
, WMPropList
*value
)
1090 wassertr(plist
->type
==WPLDictionary
);
1092 WMPLRemoveFromDictionary(plist
, key
);
1093 retainPropListByCount(key
, plist
->retainCount
);
1094 retainPropListByCount(value
, plist
->retainCount
);
1095 WMHashInsert(plist
->d
.dict
, key
, value
);
1100 WMPLRemoveFromDictionary(WMPropList
*plist
, WMPropList
*key
)
1104 wassertr(plist
->type
==WPLDictionary
);
1106 if (WMHashGetItemAndKey(plist
->d
.dict
, key
, (void**)&v
, (void**)&k
)) {
1107 WMHashRemove(plist
->d
.dict
, k
);
1108 releasePropListByCount(k
, plist
->retainCount
);
1109 releasePropListByCount(v
, plist
->retainCount
);
1115 WMPLMergeDictionaries(WMPropList
*dest
, WMPropList
*source
)
1117 WMPropList
*key
, *value
;
1120 wassertr(source
->type
==WPLDictionary
&& dest
->type
==WPLDictionary
);
1122 e
= WMEnumerateHashTable(source
->d
.dict
);
1123 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1124 WMPLPutInDictionary(dest
, key
, value
);
1132 WMPLRetain(WMPropList
*plist
)
1134 WMPropList
*key
, *value
;
1138 plist
->retainCount
++;
1140 switch(plist
->type
) {
1145 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1146 WMPLRetain(WMGetFromArray(plist
->d
.array
, i
));
1150 e
= WMEnumerateHashTable(plist
->d
.dict
);
1151 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1157 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1158 wassertrv(False
, NULL
);
1167 WMPLRelease(WMPropList
*plist
)
1169 WMPropList
*key
, *value
;
1173 plist
->retainCount
--;
1175 switch(plist
->type
) {
1177 if (plist
->retainCount
< 1) {
1178 wfree(plist
->d
.string
);
1183 if (plist
->retainCount
< 1) {
1184 WMReleaseData(plist
->d
.data
);
1189 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1190 WMPLRelease(WMGetFromArray(plist
->d
.array
, i
));
1192 if (plist
->retainCount
< 1) {
1193 WMFreeArray(plist
->d
.array
);
1198 e
= WMEnumerateHashTable(plist
->d
.dict
);
1199 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1203 if (plist
->retainCount
< 1) {
1204 WMFreeHashTable(plist
->d
.dict
);
1209 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1217 WMPLIsString(WMPropList
*plist
)
1219 return (plist
->type
== WPLString
);
1224 WMPLIsData(WMPropList
*plist
)
1226 return (plist
->type
== WPLData
);
1231 WMPLIsArray(WMPropList
*plist
)
1233 return (plist
->type
== WPLArray
);
1238 WMPLIsDictionary(WMPropList
*plist
)
1240 return (plist
->type
== WPLDictionary
);
1245 WMPLIsEqualToPL(WMPropList
*plist
, WMPropList
*other
)
1247 WMPropList
*key1
, *item1
, *item2
;
1248 WMHashEnumerator enumerator
;
1251 if (plist
->type
!= other
->type
)
1254 switch(plist
->type
) {
1256 if (caseSensitive
) {
1257 return (strcmp(plist
->d
.string
, other
->d
.string
) == 0);
1259 return (strcasecmp(plist
->d
.string
, other
->d
.string
) == 0);
1262 return WMIsDataEqualToData(plist
->d
.data
, other
->d
.data
);
1264 n
= WMGetArrayItemCount(plist
->d
.array
);
1265 if (n
!= WMGetArrayItemCount(other
->d
.array
))
1267 for (i
=0; i
<n
; i
++) {
1268 item1
= WMGetFromArray(plist
->d
.array
, i
);
1269 item2
= WMGetFromArray(other
->d
.array
, i
);
1270 if (!WMPLIsEqualToPL(item1
, item2
))
1275 if (WMCountHashTable(plist
->d
.dict
) != WMCountHashTable(other
->d
.dict
))
1277 enumerator
= WMEnumerateHashTable(plist
->d
.dict
);
1278 while (WMNextHashEnumeratorItemAndKey(&enumerator
, (void**)&item1
,
1280 item2
= WMHashGet(other
->d
.dict
, key1
);
1281 if (!item2
|| !item1
|| !WMPLIsEqualToPL(item1
, item2
))
1286 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1287 wassertrv(False
, False
);
1296 WMPLGetItemCount(WMPropList
*plist
)
1298 switch(plist
->type
) {
1301 return 0; /* should this be 1 instead? */
1303 return WMGetArrayItemCount(plist
->d
.array
);
1305 return (int)WMCountHashTable(plist
->d
.dict
);
1307 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1308 wassertrv(False
, 0);
1317 WMPLGetString(WMPropList
*plist
)
1319 wassertrv(plist
->type
==WPLString
, NULL
);
1321 return plist
->d
.string
;
1326 WMPLGetData(WMPropList
*plist
)
1328 wassertrv(plist
->type
==WPLData
, NULL
);
1330 return plist
->d
.data
;
1334 const unsigned char*
1335 WMPLGetDataBytes(WMPropList
*plist
)
1337 wassertrv(plist
->type
==WPLData
, NULL
);
1339 return WMDataBytes(plist
->d
.data
);
1344 WMPLGetDataLength(WMPropList
*plist
)
1346 wassertrv(plist
->type
==WPLData
, 0);
1348 return WMGetDataLength(plist
->d
.data
);
1353 WMPLGetFromArray(WMPropList
*plist
, int index
)
1355 wassertrv(plist
->type
==WPLArray
, NULL
);
1357 return WMGetFromArray(plist
->d
.array
, index
);
1362 WMPLGetFromDictionary(WMPropList
*plist
, WMPropList
*key
)
1364 wassertrv(plist
->type
==WPLDictionary
, NULL
);
1366 return WMHashGet(plist
->d
.dict
, key
);
1371 WMPLGetDictionaryKeys(WMPropList
*plist
)
1373 WMPropList
*array
, *key
;
1374 WMHashEnumerator enumerator
;
1376 wassertrv(plist
->type
==WPLDictionary
, NULL
);
1378 array
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1379 array
->type
= WPLArray
;
1380 array
->d
.array
= WMCreateArray(WMCountHashTable(plist
->d
.dict
));
1381 array
->retainCount
= 1;
1383 enumerator
= WMEnumerateHashTable(plist
->d
.dict
);
1384 while ((key
= WMNextHashEnumeratorKey(&enumerator
))) {
1385 WMAddToArray(array
->d
.array
, WMPLRetain(key
));
1393 WMPLGetDescription(WMPropList
*plist
, Bool indented
)
1395 return (indented
? indentedDescription(plist
, 0) : description(plist
));
1400 /* TODO: review this function's code */
1403 WMPLWriteToFile(WMPropList
*plist
, char *path
, Bool atomically
)
1414 /* Use the path name of the destination file as a prefix for the
1415 * mkstemp() call so that we can be sure that both files are on
1416 * the same filesystem and the subsequent rename() will work. */
1417 thePath
= wstrconcat(path
, ".XXXXXX");
1420 if ((fd
= mkstemp(thePath
)) < 0) {
1421 wsyserror(_("mkstemp (%s) failed"), thePath
);
1426 fchmod(fd
, 0644 & ~mask
);
1427 if ((theFile
= fdopen(fd
, "w")) == NULL
) {
1431 if (mktemp(thePath
) == NULL
) {
1432 wsyserror(_("mktemp (%s) failed"), thePath
);
1435 theFile
= fopen(thePath
, "wb");
1438 thePath
= wstrdup(path
);
1439 theFile
= fopen(thePath
, "wb");
1442 if (theFile
== NULL
) {
1443 wsyserror(_("open (%s) failed"), thePath
);
1447 desc
= indentedDescription(plist
, 0);
1449 if (fprintf(theFile
, "%s\n", desc
) != strlen(desc
)+1) {
1450 wsyserror(_("writing to file: %s failed"), thePath
);
1457 if (fclose(theFile
) != 0) {
1458 wsyserror(_("fclose (%s) failed"), thePath
);
1462 /* If we used a temporary file, we still need to rename() it be the
1463 * real file. Also, we need to try to retain the file attributes of
1464 * the original file we are overwriting (if we are) */
1466 if (rename(thePath
, path
) != 0) {
1467 wsyserror(_("rename ('%s' to '%s') failed"), thePath
, path
);
1486 WMPLShallowCopy(WMPropList
*plist
)
1488 WMPropList
*ret
= NULL
;
1489 WMPropList
*key
, *item
;
1494 switch(plist
->type
) {
1496 ret
= WMPLCreateString(plist
->d
.string
);
1499 data
= WMCreateDataWithData(plist
->d
.data
);
1500 ret
= WMPLCreateData(data
);
1501 WMReleaseData(data
);
1504 ret
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1505 ret
->type
= WPLArray
;
1506 ret
->d
.array
= WMCreateArrayWithArray(plist
->d
.array
);
1507 ret
->retainCount
= 1;
1509 for(i
=0; i
<WMGetArrayItemCount(ret
->d
.array
); i
++)
1510 WMPLRetain(WMGetFromArray(ret
->d
.array
, i
));
1514 ret
= WMPLCreateDictionary(NULL
, NULL
);
1515 e
= WMEnumerateHashTable(plist
->d
.dict
);
1516 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&item
, (void**)&key
)) {
1517 WMPLPutInDictionary(ret
, key
, item
);
1521 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1522 wassertrv(False
, NULL
);
1531 WMPLDuplicate(WMPropList
*plist
)
1533 WMPropList
*ret
= NULL
;
1534 WMPropList
*key
, *item
;
1539 switch(plist
->type
) {
1541 ret
= WMPLCreateString(plist
->d
.string
);
1544 data
= WMCreateDataWithData(plist
->d
.data
);
1545 ret
= WMPLCreateData(data
);
1546 WMReleaseData(data
);
1549 ret
= WMPLCreateArray(NULL
);
1550 for(i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1551 item
= WMPLDuplicate(WMGetFromArray(plist
->d
.array
, i
));
1552 WMAddToArray(ret
->d
.array
, item
);
1556 ret
= WMPLCreateDictionary(NULL
, NULL
);
1557 e
= WMEnumerateHashTable(plist
->d
.dict
);
1558 /* While we copy an existing dictionary there is no way that we can
1559 * have duplicate keys, so we don't need to first remove a key/value
1560 * pair before inserting the new key/value.
1562 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&item
, (void**)&key
)) {
1563 WMHashInsert(ret
->d
.dict
, WMPLDuplicate(key
), WMPLDuplicate(item
));
1567 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1568 wassertrv(False
, NULL
);
1577 WMPLGetWithDescription(char *desc
)
1579 WMPropList
*plist
= NULL
;
1582 pldata
= (PLData
*) wmalloc(sizeof(PLData
));
1583 memset(pldata
, 0, sizeof(PLData
));
1585 pldata
->lineNumber
= 1;
1587 plist
= getPropList(pldata
);
1589 if (getNonSpaceChar(pldata
)!=0 && plist
) {
1590 COMPLAIN(pldata
, _("extra data after end of property list"));
1592 * We can't just ignore garbage after the end of the description
1593 * (especially if the description was read from a file), because
1594 * the "garbage" can be the real data and the real garbage is in
1595 * fact in the beginning of the file (which is now inside plist)
1608 WMPLReadFromFile(char *file
)
1610 WMPropList
*plist
= NULL
;
1616 f
= fopen(file
, "r");
1618 wsyserror(_("could not open domain file %s for reading"), file
);
1622 if (stat(file
, &stbuf
)==0) {
1623 length
= (size_t) stbuf
.st_size
;
1625 wsyserror(_("could not get size for domain file %s"), file
);
1630 pldata
= (PLData
*) wmalloc(sizeof(PLData
));
1631 memset(pldata
, 0, sizeof(PLData
));
1632 pldata
->ptr
= (char*) wmalloc(length
+1);
1633 pldata
->filename
= file
;
1634 pldata
->lineNumber
= 1;
1636 if (fread(pldata
->ptr
, length
, 1, f
) != 1) {
1637 wsyserror(_("error reading from file %s"), file
);
1642 pldata
->ptr
[length
] = 0;
1644 plist
= getPropList(pldata
);
1646 if (getNonSpaceChar(pldata
)!=0 && plist
) {
1647 COMPLAIN(pldata
, _("extra data after end of property list"));
1649 * We can't just ignore garbage after the end of the description
1650 * (especially if the description was read from a file), because
1651 * the "garbage" can be the real data and the real garbage is in
1652 * fact in the beginning of the file (which is now inside plist)