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"));
703 WMAppendDataBytes(data
, buf
, len
);
705 plist
= WMCreatePLData(data
);
713 getPLArray(PLData
*pldata
)
718 WMPropList
*array
, *obj
;
720 array
= WMCreatePLArray(NULL
);
723 c
= getNonSpaceChar(pldata
);
725 COMPLAIN(pldata
, _("unterminated PropList array"));
728 } else if (c
== ')') {
730 } else if (c
== ',') {
731 /* continue normally */
733 COMPLAIN(pldata
, _("missing , or unterminated PropList array"));
741 obj
= getPropList(pldata
);
743 COMPLAIN(pldata
, _("could not get PropList array element"));
747 WMAddToPLArray(array
, obj
);
748 WMReleasePropList(obj
);
752 WMReleasePropList(array
);
761 getPLDictionary(PLData
*pldata
)
765 WMPropList
*dict
, *key
, *value
;
767 dict
= WMCreatePLDictionary(NULL
, NULL
);
770 c
= getNonSpaceChar(pldata
);
772 COMPLAIN(pldata
, _("unterminated PropList dictionary"));
779 DPUT("getting PropList dictionary key");
781 key
= getPLData(pldata
);
782 } else if (c
== '"') {
783 key
= getPLQString(pldata
);
784 } else if (ISSTRINGABLE(c
)) {
786 key
= getPLString(pldata
);
789 COMPLAIN(pldata
, _("missing PropList dictionary key"));
791 COMPLAIN(pldata
, _("missing PropList dictionary entry key "
792 "or unterminated dictionary"));
799 COMPLAIN(pldata
, _("error parsing PropList dictionary key"));
804 c
= getNonSpaceChar(pldata
);
806 WMReleasePropList(key
);
807 COMPLAIN(pldata
, _("missing = in PropList dictionary entry"));
812 DPUT("getting PropList dictionary entry value for key");
813 value
= getPropList(pldata
);
815 COMPLAIN(pldata
, _("error parsing PropList dictionary entry value"));
816 WMReleasePropList(key
);
821 c
= getNonSpaceChar(pldata
);
823 COMPLAIN(pldata
, _("missing ; in PropList dictionary entry"));
824 WMReleasePropList(key
);
825 WMReleasePropList(value
);
830 WMPutInPLDictionary(dict
, key
, value
);
831 WMReleasePropList(key
);
832 WMReleasePropList(value
);
836 WMReleasePropList(dict
);
845 getPropList(PLData
*pldata
)
850 c
= getNonSpaceChar(pldata
);
854 DPUT("End of PropList");
859 DPUT("Getting PropList dictionary");
860 plist
= getPLDictionary(pldata
);
864 DPUT("Getting PropList srrsy");
865 plist
= getPLArray(pldata
);
869 DPUT("Getting PropList data");
870 plist
= getPLData(pldata
);
874 DPUT("Getting PropList quoted string");
875 plist
= getPLQString(pldata
);
879 if (ISSTRINGABLE(c
)) {
880 DPUT("Getting PropList string");
882 plist
= getPLString(pldata
);
884 COMPLAIN(pldata
, _("was expecting a string, data, array or "
885 "dictionary. If it's a string, try enclosing "
887 if (c
=='#' || c
=='/') {
888 wwarning(_("Comments are not allowed inside WindowMaker owned"
901 WMPLSetCaseSensitive(Bool caseSensitiveness
)
903 caseSensitive
= caseSensitiveness
;
908 WMCreatePLString(char *str
)
912 wassertrv(str
!=NULL
, NULL
);
914 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
916 plist
->type
= WPLString
;
917 plist
->d
.string
= wstrdup(str
);
918 plist
->retainCount
= 1;
925 WMCreatePLData(WMData
*data
)
929 wassertrv(data
!=NULL
, NULL
);
931 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
933 plist
->type
= WPLData
;
934 plist
->d
.data
= WMRetainData(data
);
935 plist
->retainCount
= 1;
942 WMCreatePLDataWithBytes(unsigned char *bytes
, unsigned int length
)
946 wassertrv(bytes
!=NULL
, NULL
);
948 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
950 plist
->type
= WPLData
;
951 plist
->d
.data
= WMCreateDataWithBytes(bytes
, length
);
952 plist
->retainCount
= 1;
959 WMCreatePLDataWithBytesNoCopy(unsigned char *bytes
, unsigned int length
,
960 WMFreeDataProc
*destructor
)
964 wassertrv(bytes
!=NULL
, NULL
);
966 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
968 plist
->type
= WPLData
;
969 plist
->d
.data
= WMCreateDataWithBytesNoCopy(bytes
, length
, destructor
);
970 plist
->retainCount
= 1;
977 WMCreatePLArray(WMPropList
*elem
, ...)
979 WMPropList
*plist
, *nelem
;
982 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
983 plist
->type
= WPLArray
;
984 plist
->d
.array
= WMCreateArray(4);
985 plist
->retainCount
= 1;
990 WMAddToArray(plist
->d
.array
, WMRetainPropList(elem
));
995 nelem
= va_arg(ap
, WMPropList
*);
1000 WMAddToArray(plist
->d
.array
, WMRetainPropList(nelem
));
1006 WMCreatePLDictionary(WMPropList
*key
, WMPropList
*value
, ...)
1008 WMPropList
*plist
, *nkey
, *nvalue
, *k
, *v
;
1011 plist
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1012 plist
->type
= WPLDictionary
;
1013 plist
->d
.dict
= WMCreateHashTable(WMPropListHashCallbacks
);
1014 plist
->retainCount
= 1;
1019 WMHashInsert(plist
->d
.dict
, WMRetainPropList(key
), WMRetainPropList(value
));
1021 va_start(ap
, value
);
1024 nkey
= va_arg(ap
, WMPropList
*);
1029 nvalue
= va_arg(ap
, WMPropList
*);
1034 if (WMHashGetItemAndKey(plist
->d
.dict
, nkey
, (void**)&v
, (void**)&k
)) {
1035 WMHashRemove(plist
->d
.dict
, k
);
1036 WMReleasePropList(k
);
1037 WMReleasePropList(v
);
1039 WMHashInsert(plist
->d
.dict
, WMRetainPropList(nkey
),
1040 WMRetainPropList(nvalue
));
1046 WMRetainPropList(WMPropList
*plist
)
1048 WMPropList
*key
, *value
;
1052 plist
->retainCount
++;
1054 switch(plist
->type
) {
1059 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1060 WMRetainPropList(WMGetFromArray(plist
->d
.array
, i
));
1064 e
= WMEnumerateHashTable(plist
->d
.dict
);
1065 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1066 WMRetainPropList(key
);
1067 WMRetainPropList(value
);
1071 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1072 wassertrv(False
, NULL
);
1081 WMReleasePropList(WMPropList
*plist
)
1083 WMPropList
*key
, *value
;
1087 plist
->retainCount
--;
1089 switch(plist
->type
) {
1091 if (plist
->retainCount
< 1) {
1092 wfree(plist
->d
.string
);
1097 if (plist
->retainCount
< 1) {
1098 WMReleaseData(plist
->d
.data
);
1103 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1104 WMReleasePropList(WMGetFromArray(plist
->d
.array
, i
));
1106 if (plist
->retainCount
< 1) {
1107 WMFreeArray(plist
->d
.array
);
1112 e
= WMEnumerateHashTable(plist
->d
.dict
);
1113 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1114 WMReleasePropList(key
);
1115 WMReleasePropList(value
);
1117 if (plist
->retainCount
< 1) {
1118 WMFreeHashTable(plist
->d
.dict
);
1123 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1131 WMInsertInPLArray(WMPropList
*plist
, int index
, WMPropList
*item
)
1133 wassertr(plist
->type
==WPLArray
);
1135 retainPropListByCount(item
, plist
->retainCount
);
1136 WMInsertInArray(plist
->d
.array
, index
, item
);
1141 WMAddToPLArray(WMPropList
*plist
, WMPropList
*item
)
1143 wassertr(plist
->type
==WPLArray
);
1145 retainPropListByCount(item
, plist
->retainCount
);
1146 WMAddToArray(plist
->d
.array
, item
);
1151 WMDeleteFromPLArray(WMPropList
*plist
, int index
)
1155 wassertr(plist
->type
==WPLArray
);
1157 item
= WMGetFromArray(plist
->d
.array
, index
);
1159 WMDeleteFromArray(plist
->d
.array
, index
);
1160 releasePropListByCount(item
, plist
->retainCount
);
1166 WMRemoveFromPLArray(WMPropList
*plist
, WMPropList
*item
)
1171 wassertr(plist
->type
==WPLArray
);
1173 for (i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1174 iPtr
= WMGetFromArray(plist
->d
.array
, i
);
1175 if (WMIsPropListEqualTo(item
, iPtr
)) {
1176 WMDeleteFromArray(plist
->d
.array
, i
);
1177 releasePropListByCount(iPtr
, plist
->retainCount
);
1185 WMPutInPLDictionary(WMPropList
*plist
, WMPropList
*key
, WMPropList
*value
)
1187 wassertr(plist
->type
==WPLDictionary
);
1189 /*WMRetainPropList(key);*/
1190 WMRemoveFromPLDictionary(plist
, key
);
1191 retainPropListByCount(key
, plist
->retainCount
);
1192 retainPropListByCount(value
, plist
->retainCount
);
1193 WMHashInsert(plist
->d
.dict
, key
, value
);
1194 /*WMReleasePropList(key);*/
1199 WMRemoveFromPLDictionary(WMPropList
*plist
, WMPropList
*key
)
1203 wassertr(plist
->type
==WPLDictionary
);
1205 if (WMHashGetItemAndKey(plist
->d
.dict
, key
, (void**)&v
, (void**)&k
)) {
1206 WMHashRemove(plist
->d
.dict
, k
);
1207 releasePropListByCount(k
, plist
->retainCount
);
1208 releasePropListByCount(v
, plist
->retainCount
);
1214 WMMergePLDictionaries(WMPropList
*dest
, WMPropList
*source
)
1216 WMPropList
*key
, *value
;
1219 wassertr(source
->type
==WPLDictionary
&& dest
->type
==WPLDictionary
);
1221 e
= WMEnumerateHashTable(source
->d
.dict
);
1222 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&value
, (void**)&key
)) {
1223 WMPutInPLDictionary(dest
, key
, value
);
1231 WMGetPropListItemCount(WMPropList
*plist
)
1233 switch(plist
->type
) {
1236 return 0; /* should this be 1 instead? */
1238 return WMGetArrayItemCount(plist
->d
.array
);
1240 return (int)WMCountHashTable(plist
->d
.dict
);
1242 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1243 wassertrv(False
, 0);
1252 WMIsPLString(WMPropList
*plist
)
1254 return (plist
->type
== WPLString
);
1259 WMIsPLData(WMPropList
*plist
)
1261 return (plist
->type
== WPLData
);
1266 WMIsPLArray(WMPropList
*plist
)
1268 return (plist
->type
== WPLArray
);
1273 WMIsPLDictionary(WMPropList
*plist
)
1275 return (plist
->type
== WPLDictionary
);
1280 WMIsPropListEqualTo(WMPropList
*plist
, WMPropList
*other
)
1282 WMPropList
*key1
, *item1
, *item2
;
1283 WMHashEnumerator enumerator
;
1286 if (plist
->type
!= other
->type
)
1289 switch(plist
->type
) {
1291 if (caseSensitive
) {
1292 return (strcmp(plist
->d
.string
, other
->d
.string
) == 0);
1294 return (strcasecmp(plist
->d
.string
, other
->d
.string
) == 0);
1297 return WMIsDataEqualToData(plist
->d
.data
, other
->d
.data
);
1299 n
= WMGetArrayItemCount(plist
->d
.array
);
1300 if (n
!= WMGetArrayItemCount(other
->d
.array
))
1302 for (i
=0; i
<n
; i
++) {
1303 item1
= WMGetFromArray(plist
->d
.array
, i
);
1304 item2
= WMGetFromArray(other
->d
.array
, i
);
1305 if (!WMIsPropListEqualTo(item1
, item2
))
1310 if (WMCountHashTable(plist
->d
.dict
) != WMCountHashTable(other
->d
.dict
))
1312 enumerator
= WMEnumerateHashTable(plist
->d
.dict
);
1313 while (WMNextHashEnumeratorItemAndKey(&enumerator
, (void**)&item1
,
1315 item2
= WMHashGet(other
->d
.dict
, key1
);
1316 if (!item2
|| !item1
|| !WMIsPropListEqualTo(item1
, item2
))
1321 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1322 wassertrv(False
, False
);
1331 WMGetFromPLString(WMPropList
*plist
)
1333 wassertrv(plist
->type
==WPLString
, NULL
);
1335 return plist
->d
.string
;
1340 WMGetFromPLData(WMPropList
*plist
)
1342 wassertrv(plist
->type
==WPLData
, NULL
);
1344 return plist
->d
.data
;
1348 const unsigned char*
1349 WMGetPLDataBytes(WMPropList
*plist
)
1351 wassertrv(plist
->type
==WPLData
, NULL
);
1353 return WMDataBytes(plist
->d
.data
);
1358 WMGetPLDataLength(WMPropList
*plist
)
1360 wassertrv(plist
->type
==WPLData
, 0);
1362 return WMGetDataLength(plist
->d
.data
);
1367 WMGetFromPLArray(WMPropList
*plist
, int index
)
1369 wassertrv(plist
->type
==WPLArray
, NULL
);
1371 return WMGetFromArray(plist
->d
.array
, index
);
1376 WMGetFromPLDictionary(WMPropList
*plist
, WMPropList
*key
)
1378 wassertrv(plist
->type
==WPLDictionary
, NULL
);
1380 return WMHashGet(plist
->d
.dict
, key
);
1385 WMGetPLDictionaryKeys(WMPropList
*plist
)
1387 WMPropList
*array
, *key
;
1388 WMHashEnumerator enumerator
;
1390 wassertrv(plist
->type
==WPLDictionary
, NULL
);
1392 array
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1393 array
->type
= WPLArray
;
1394 array
->d
.array
= WMCreateArray(WMCountHashTable(plist
->d
.dict
));
1395 array
->retainCount
= 1;
1397 enumerator
= WMEnumerateHashTable(plist
->d
.dict
);
1398 while ((key
= WMNextHashEnumeratorKey(&enumerator
))) {
1399 WMAddToArray(array
->d
.array
, WMRetainPropList(key
));
1407 WMShallowCopyPropList(WMPropList
*plist
)
1409 WMPropList
*ret
= NULL
;
1410 WMPropList
*key
, *item
;
1415 switch(plist
->type
) {
1417 ret
= WMCreatePLString(plist
->d
.string
);
1420 data
= WMCreateDataWithData(plist
->d
.data
);
1421 ret
= WMCreatePLData(data
);
1422 WMReleaseData(data
);
1425 ret
= (WMPropList
*)wmalloc(sizeof(W_PropList
));
1426 ret
->type
= WPLArray
;
1427 ret
->d
.array
= WMCreateArrayWithArray(plist
->d
.array
);
1428 ret
->retainCount
= 1;
1430 for(i
=0; i
<WMGetArrayItemCount(ret
->d
.array
); i
++)
1431 WMRetainPropList(WMGetFromArray(ret
->d
.array
, i
));
1435 ret
= WMCreatePLDictionary(NULL
, NULL
);
1436 e
= WMEnumerateHashTable(plist
->d
.dict
);
1437 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&item
, (void**)&key
)) {
1438 WMPutInPLDictionary(ret
, key
, item
);
1442 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1443 wassertrv(False
, NULL
);
1452 WMDeepCopyPropList(WMPropList
*plist
)
1454 WMPropList
*ret
= NULL
;
1455 WMPropList
*key
, *item
;
1460 switch(plist
->type
) {
1462 ret
= WMCreatePLString(plist
->d
.string
);
1465 data
= WMCreateDataWithData(plist
->d
.data
);
1466 ret
= WMCreatePLData(data
);
1467 WMReleaseData(data
);
1470 ret
= WMCreatePLArray(NULL
);
1471 for(i
=0; i
<WMGetArrayItemCount(plist
->d
.array
); i
++) {
1472 item
= WMDeepCopyPropList(WMGetFromArray(plist
->d
.array
, i
));
1473 WMAddToArray(ret
->d
.array
, item
);
1477 ret
= WMCreatePLDictionary(NULL
, NULL
);
1478 e
= WMEnumerateHashTable(plist
->d
.dict
);
1479 /* While we copy an existing dictionary there is no way that we can
1480 * have duplicate keys, so we don't need to first remove a key/value
1481 * pair before inserting the new key/value.
1483 while (WMNextHashEnumeratorItemAndKey(&e
, (void**)&item
, (void**)&key
)) {
1484 WMHashInsert(ret
->d
.dict
, WMDeepCopyPropList(key
),
1485 WMDeepCopyPropList(item
));
1489 wwarning(_("Used proplist functions on non-WMPropLists objects"));
1490 wassertrv(False
, NULL
);
1499 WMCreatePropListFromDescription(char *desc
)
1501 WMPropList
*plist
= NULL
;
1504 pldata
= (PLData
*) wmalloc(sizeof(PLData
));
1505 memset(pldata
, 0, sizeof(PLData
));
1507 pldata
->lineNumber
= 1;
1509 plist
= getPropList(pldata
);
1511 if (getNonSpaceChar(pldata
)!=0 && plist
) {
1512 COMPLAIN(pldata
, _("extra data after end of property list"));
1514 * We can't just ignore garbage after the end of the description
1515 * (especially if the description was read from a file), because
1516 * the "garbage" can be the real data and the real garbage is in
1517 * fact in the beginning of the file (which is now inside plist)
1519 WMReleasePropList(plist
);
1530 WMGetPropListDescription(WMPropList
*plist
, Bool indented
)
1532 return (indented
? indentedDescription(plist
, 0) : description(plist
));
1537 WMReadPropListFromFile(char *file
)
1539 WMPropList
*plist
= NULL
;
1545 f
= fopen(file
, "r");
1547 wsyserror(_("could not open domain file %s for reading"), file
);
1551 if (stat(file
, &stbuf
)==0) {
1552 length
= (size_t) stbuf
.st_size
;
1554 wsyserror(_("could not get size for domain file %s"), file
);
1559 pldata
= (PLData
*) wmalloc(sizeof(PLData
));
1560 memset(pldata
, 0, sizeof(PLData
));
1561 pldata
->ptr
= (char*) wmalloc(length
+1);
1562 pldata
->filename
= file
;
1563 pldata
->lineNumber
= 1;
1565 if (fread(pldata
->ptr
, length
, 1, f
) != 1) {
1566 wsyserror(_("error reading from file %s"), file
);
1571 pldata
->ptr
[length
] = 0;
1573 plist
= getPropList(pldata
);
1575 if (getNonSpaceChar(pldata
)!=0 && plist
) {
1576 COMPLAIN(pldata
, _("extra data after end of property list"));
1578 * We can't just ignore garbage after the end of the description
1579 * (especially if the description was read from a file), because
1580 * the "garbage" can be the real data and the real garbage is in
1581 * fact in the beginning of the file (which is now inside plist)
1583 WMReleasePropList(plist
);
1596 /* TODO: review this function's code */
1599 WMWritePropListToFile(WMPropList
*plist
, char *path
, Bool atomically
)
1610 /* Use the path name of the destination file as a prefix for the
1611 * mkstemp() call so that we can be sure that both files are on
1612 * the same filesystem and the subsequent rename() will work. */
1613 thePath
= wstrconcat(path
, ".XXXXXX");
1616 if ((fd
= mkstemp(thePath
)) < 0) {
1617 wsyserror(_("mkstemp (%s) failed"), thePath
);
1622 fchmod(fd
, 0644 & ~mask
);
1623 if ((theFile
= fdopen(fd
, "w")) == NULL
) {
1627 if (mktemp(thePath
) == NULL
) {
1628 wsyserror(_("mktemp (%s) failed"), thePath
);
1631 theFile
= fopen(thePath
, "wb");
1634 thePath
= wstrdup(path
);
1635 theFile
= fopen(thePath
, "wb");
1638 if (theFile
== NULL
) {
1639 wsyserror(_("open (%s) failed"), thePath
);
1643 desc
= indentedDescription(plist
, 0);
1645 if (fprintf(theFile
, "%s\n", desc
) != strlen(desc
)+1) {
1646 wsyserror(_("writing to file: %s failed"), thePath
);
1653 if (fclose(theFile
) != 0) {
1654 wsyserror(_("fclose (%s) failed"), thePath
);
1658 /* If we used a temporary file, we still need to rename() it be the
1659 * real file. Also, we need to try to retain the file attributes of
1660 * the original file we are overwriting (if we are) */
1662 if (rename(thePath
, path
) != 0) {
1663 wsyserror(_("rename ('%s' to '%s') failed"), thePath
, path
);