Browse code

Neue README.md

Nat! authored on 15/02/2013 13:21:02
Showing 3 changed files
... ...
@@ -5,180 +5,180 @@ Just say *sudo make install* and the files will end up in /usr/local.
5 5
 ---
6 6
 
7 7
 ## man pages
8
-## mulle-plist-compress
9
-
10
-<p style="margin-top: 1em" valign="top"><b>NAME</b></p>
11
-
12
-<p style="margin-left:8%;"><b>mulle-plist-compress</b>
13
-&mdash; Compress and format a property list for inclusion in
14
-C code.</p>
8
+## mulle-plist-from-files
9
+<pre>
10
+mulle‐plist‐from‐files(8) BSD System Manager’s Manualmulle‐plist‐from‐files(8)
15 11
 
12
+NAME
13
+     mulle‐plist‐from‐files — Combine multiple files into a single property
14
+     list
16 15
 
17
-<p style="margin-top: 1em" valign="top"><b>SYNOPSIS</b></p>
16
+SYNOPSIS
17
+     mulle‐plist‐from‐files file [file ...]
18 18
 
19
-<p style="margin-left:40%;"><b>mulle-plist-compress</b>
20
-[<b>&minus;s&nbsp;</b><i>style</i>]
21
-[<b>&minus;c&nbsp;</b><i>compression</i>]
22
-[<b>&minus;f&nbsp;</b><i>format</i>]</p>
19
+DESCRIPTION
20
+     Reads, possibly recursively, a bunch of files and creates a property
21
+     plist from them. This property list is then written to standard output.
23 22
 
23
+SEE ALSO
24
+     mulle‐plist‐from‐files(8)
24 25
 
25
-<p style="margin-top: 1em" valign="top"><b>DESCRIPTION</b></p>
26
+AUTHOR
27
+     Coded by Nat! 2013, Mulle kybernetiK. www.mulle‐kybernetik.com. The
28
+     lastest version should be available on github. http://github.com/mulle‐
29
+     nat/mulle‐plist‐utilities
26 30
 
27
-<p style="margin-left:8%;">Reads a <i>property plist</i>
28
-from standard input and writes it&rsquo;s result to standard
29
-output. The <i>property list</i> is by default space
30
-optimized and escaped to be used in a C-String. The options
31
-are processed in the order s, c, f.</p>
31
+Darwin			       February 15, 2013			Darwin
32
+</pre>
33
+---
34
+## mulle-plist-compress
35
+<pre>
36
+mulle‐plist‐compress(8)   BSD System Manager’s Manual  mulle‐plist‐compress(8)
32 37
 
33
-<p style="margin-left:8%; margin-top: 1em">The following
34
-options are available:</p>
38
+NAME
39
+     mulle‐plist‐compress — Compress and format a property list for inclusion
40
+     in C code.
35 41
 
42
+SYNOPSIS
43
+     mulle‐plist‐compress [−s style] [−c compression] [−f format]
36 44
 
37
-<p style="margin-top: 1em" valign="top"><b>&minus;s</b></p>
45
+DESCRIPTION
46
+     Reads a property plist from standard input and writes it’s result to
47
+     standard output. The property list is by default space optimized and
48
+     escaped to be used in a C‐String. The options are processed in the order
49
+     s, c, f.
38 50
 
39
-<p style="margin-left:22%; margin-top: 1em">Change the
40
-style of the produced property list:</p>
51
+     The following options are available:
41 52
 
53
+     −s       Change the style of the produced property list:
42 54
 
43
-<p style="margin-left:22%; margin-top: 1em"><b>condensed</b>
44
-only outputs a minimal number of characters for the property
45
-list (default).</p>
55
+	      condensed only outputs a minimal number of characters for the
56
+	      property list (default).
46 57
 
47
-<p style="margin-left:22%; margin-top: 1em"><b>pretty</b>
48
-is the output created by -[NSObject description].</p>
58
+	      pretty is the output created by ‐[NSObject description].
49 59
 
50
-<p style="margin-left:22%; margin-top: 1em"><b>xml</b>
51
-produces XML property list output. <b>binary</b> produces
52
-binary property list output.</p>
60
+	      xml produces XML property list output.  binary produces binary
61
+	      property list output.
53 62
 
63
+     −c       Use a binary compression method:
54 64
 
55
-<p style="margin-top: 1em" valign="top"><b>&minus;c</b></p>
65
+	      none to not compress (default), use
56 66
 
57
-<p style="margin-left:22%; margin-top: 1em">Use a binary
58
-compression method:</p>
67
+	      zlib to create a zlib compressed blob.
59 68
 
60
-<p style="margin-left:22%; margin-top: 1em"><b>none</b> to
61
-not compress (default), use</p>
69
+     −f       Choose an output format:
62 70
 
63
-<p style="margin-left:22%; margin-top: 1em"><b>zlib</b> to
64
-create a zlib compressed blob.</p>
71
+	      escaped for inclusion into a C‐String (default). Not useful in
72
+	      combination with compression.
65 73
 
74
+	      plain for output as is.
66 75
 
67
-<p style="margin-top: 1em" valign="top"><b>&minus;f</b></p>
76
+	      hex to output in hexadecimal format for inclusion in a unsigned
77
+	      char C‐Array.
68 78
 
69
-<p style="margin-left:22%; margin-top: 1em">Choose an
70
-output format:</p>
79
+ENVIRONMENT
80
+     MULLE_PLIST_HEADER  The contents of this environment variable are
81
+			 prepended to the output.
71 82
 
72
-<p style="margin-left:22%; margin-top: 1em"><b>escaped</b>
73
-for inclusion into a C-String (default). Not useful in
74
-combination with compression.</p>
83
+     MULLE_PLIST_FOOTER  The contents of this environment variable are
84
+			 appended to the output.
75 85
 
76
-<p style="margin-left:22%; margin-top: 1em"><b>plain</b>
77
-for output as is.</p>
86
+SEE ALSO
87
+     mulle‐plist‐from‐files(8) mulle‐plist‐hack(8) mulle‐plist‐fix(8)
78 88
 
79
-<p style="margin-left:22%; margin-top: 1em"><b>hex</b> to
80
-output in hexadecimal format for inclusion in a unsigned
81
-char C-Array.</p>
89
+AUTHOR
90
+     Coded by Nat! 2013, Mulle kybernetiK. www.mulle‐kybernetik.com. The
91
+     lastest version should be available on github. http://github.com/mulle‐
92
+     nat/mulle‐plist‐utilities
82 93
 
94
+Darwin			       February 15, 2013			Darwin
95
+</pre>
83 96
 ---
84 97
 ## mulle-plist-fix
98
+<pre>
99
+mulle‐plist‐fix(8)	  BSD System Manager’s Manual	    mulle‐plist‐fix(8)
85 100
 
86
-<p style="margin-top: 1em" valign="top"><b>NAME</b></p>
87
-
88
-<p style="margin-left:8%;"><b>mulle-plist-fix</b> &mdash;
89
-Fix ancient property list files</p>
101
+NAME
102
+     mulle‐plist‐fix — Fix ancient property list files
90 103
 
104
+SYNOPSIS
105
+     mulle‐plist‐fix file [file ...]
91 106
 
92
-<p style="margin-top: 1em" valign="top"><b>SYNOPSIS</b></p>
107
+DESCRIPTION
108
+     Reads very, very old property list format from standard input and a more
109
+     modern property plist format is then then written to standard output.
93 110
 
94
-<p style="margin-left:32%;"><b>mulle-plist-fix</b>
95
-<i>file</i> [<i>file&nbsp;...</i>]</p>
111
+SEE ALSO
112
+     mulle‐plist‐fix(8)
96 113
 
114
+AUTHOR
115
+     Coded by Nat! 2013, Mulle kybernetiK. www.mulle‐kybernetik.com. The
116
+     lastest version should be available on github. http://github.com/mulle‐
117
+     nat/mulle‐plist‐utilities
97 118
 
98
-<p style="margin-top: 1em" valign="top"><b>DESCRIPTION</b></p>
99
-
100
-<p style="margin-left:8%;">Reads very, very old <i>property
101
-list</i> format from standard input and a more modern
102
-<i>property plist</i> format is then then written to
103
-standard output.</p>
104
-
105
-## mulle-plist-from-files
106
-
107
-<p style="margin-top: 1em" valign="top"><b>NAME</b></p>
108
-
109
-<p style="margin-left:8%;"><b>mulle-plist-from-files</b>
110
-&mdash; Combine multiple files into a single property
111
-list</p>
112
-
113
-
114
-<p style="margin-top: 1em" valign="top"><b>SYNOPSIS</b></p>
115
-
116
-<p style="margin-left:43%;"><b>mulle-plist-from-files</b>
117
-<i>file</i> [<i>file&nbsp;...</i>]</p>
118
-
119
-
120
-<p style="margin-top: 1em" valign="top"><b>DESCRIPTION</b></p>
121
-
122
-<p style="margin-left:8%;">Reads, possibly recursively, a
123
-bunch of files and creates a <i>property plist</i> from
124
-them. This <i>property list</i> is then written to standard
125
-output.</p>
126
-
119
+Darwin			       February 15, 2013			Darwin
120
+</pre>
127 121
 ---
128 122
 ## mulle-plist-hack
123
+<pre>
124
+mulle‐plist‐hack(8)	  BSD System Manager’s Manual	   mulle‐plist‐hack(8)
129 125
 
130
-<p style="margin-top: 1em" valign="top"><b>NAME</b></p>
126
+NAME
127
+     mulle‐plist‐hack — Print, delete or change single key values in a prop‐
128
+     erty list.
131 129
 
132
-<p style="margin-left:8%;"><b>mulle-plist-hack,
133
-Other_name_for_same_program(), Yet another name for the same
134
-program.</b> &mdash; This line parsed for whatis
135
-database.</p>
130
+SYNOPSIS
131
+     mulle‐plist‐hack [−s style] [−c compression] [−f format]
136 132
 
133
+DESCRIPTION
134
+     Reads a property plist from standard input, does some user supplied
135
+     manipulations on it and writes it’s result to standard output.
137 136
 
138
-<p style="margin-top: 1em" valign="top"><b>SYNOPSIS</b></p>
137
+     The following options are available:
139 138
 
140
-<p style="margin-left:35%;"><b>mulle-plist-hack,</b>
141
-[<b>&minus;abcd</b>] [<b>&minus;a&nbsp;</b><i>path</i>]
142
-[<i>file</i>] [<i>file&nbsp;...</i>] <i>arg0</i> arg2
143
-...</p>
139
+     −s       Change the style of the produced property list:
144 140
 
141
+	      condensed only outputs a minimal number of characters for the
142
+	      property list (default).
145 143
 
146
-<p style="margin-top: 1em" valign="top"><b>DESCRIPTION</b></p>
144
+	      pretty is the output created by ‐[NSObject description].
147 145
 
148
-<p style="margin-left:8%;">Use the .Nm macro to refer to
149
-your program throughout the man page like such:
150
-<b>mulle-plist-hack,</b> Underlining is accomplished with
151
-the .Ar macro like this: <i>underlined text</i>.</p>
146
+	      xml produces XML property list output.  binary produces binary
147
+	      property list output.
152 148
 
153
-<p style="margin-left:8%; margin-top: 1em">A list of items
154
-with descriptions:</p>
149
+     −c       Use a binary compression method:
155 150
 
156
-<p style="margin-top: 1em" valign="top">item a</p>
151
+	      none to not compress (default), use
157 152
 
158
-<p style="margin-left:22%; margin-top: 1em">Description of
159
-item a</p>
153
+	      zlib to create a zlib compressed blob.
160 154
 
161
-<p style="margin-top: 1em" valign="top">item b</p>
155
+     −f       Choose an output format:
162 156
 
163
-<p style="margin-left:22%; margin-top: 1em">Description of
164
-item b</p>
157
+	      escaped for inclusion into a C‐String (default). Not useful in
158
+	      combination with compression.
165 159
 
166
-<p style="margin-left:8%; margin-top: 1em">A list of flags
167
-and their descriptions:</p>
160
+	      plain for output as is.
168 161
 
162
+	      hex to output in hexadecimal format for inclusion in a unsigned
163
+	      char C‐Array.
169 164
 
170
-<p style="margin-top: 1em" valign="top"><b>&minus;a</b></p>
165
+ENVIRONMENT
166
+     MULLE_PLIST_HEADER  The contents of this environment variable are
167
+			 prepended to the output.
171 168
 
172
-<p style="margin-left:22%; margin-top: 1em">Description of
173
--a flag</p>
169
+     MULLE_PLIST_FOOTER  The contents of this environment variable are
170
+			 appended to the output.
174 171
 
172
+SEE ALSO
173
+     mulle‐plist‐from‐files(8) mulle‐plist‐hack(8) mulle‐plist‐fix(8)
175 174
 
176
-<p style="margin-top: 1em" valign="top"><b>&minus;b</b></p>
177
-
178
-<p style="margin-left:22%; margin-top: 1em">Description of
179
--b flag</p>
175
+AUTHOR
176
+     Coded by Nat! 2013, Mulle kybernetiK. www.mulle‐kybernetik.com. The
177
+     lastest version should be available on github. http://github.com/mulle‐
178
+     nat/mulle‐plist‐utilities
180 179
 
180
+Darwin			       February 15, 2013			Darwin
181
+</pre>
181 182
 ---
182 183
 ---
183 184
 
184 185
new file mode 100644
... ...
@@ -0,0 +1,279 @@
0
+#import "NSPropertyListSerialization+MullePlistReader.h"
1
+#include <ctype.h>
2
+
3
+
4
+#define TRY_VALIANTLY_TO_CONVERT  0
5
+
6
+
7
+@implementation NSPropertyListSerialization ( MullePlistReader)
8
+
9
+
10
+static inline int   iswhite( int c)
11
+{
12
+   return( c == ' ' || c == '\n' || c == '\r' || c == '\t');
13
+}
14
+
15
+
16
+static id  _parse_object( char **s, unsigned int *len);
17
+
18
+static int   skip_white( char **s, unsigned int *len)
19
+{
20
+    while( *len)
21
+    {
22
+        if( ! iswhite( **s))
23
+            return( 0);
24
+        ++*s;
25
+        --*len;
26
+    }
27
+    return( -1);
28
+}
29
+
30
+/*
31
+static NSString  *slurp_identifier( char **s, unsigned int *len)
32
+{
33
+    int    c;
34
+    char   *memo;
35
+
36
+    memo = *s;
37
+    while( *len)
38
+    {
39
+        c = **s;
40
+        if( ! (isalnum( c) || c == '_'))
41
+           break;
42
+        ++*s;
43
+        --*len;
44
+    }
45
+    return( [NSString stringWithCString:memo
46
+                                 length:*s - memo]);
47
+}
48
+*/
49
+
50
+static id   _parse_value( char **s, unsigned int *len)
51
+{
52
+    int        c;
53
+    char       *memo;
54
+    int        quoted;
55
+    NSString   *string;
56
+    
57
+    quoted = **s == '"';
58
+    if( quoted)
59
+    {
60
+        ++*s;
61
+        --*len;
62
+    }
63
+    
64
+    memo = *s;
65
+    while( *len)
66
+    {
67
+        c = **s;
68
+        if( quoted)
69
+        {
70
+            if( c == '"')
71
+                break;
72
+        }
73
+        else
74
+        {
75
+            if( iswhite( c) || c == ',' || c == ';')
76
+                break;
77
+        }
78
+        ++*s;
79
+        --*len;
80
+    }
81
+    
82
+
83
+    string = [NSString stringWithCString:memo
84
+                                  length:*s - memo];
85
+    if( quoted)
86
+    {
87
+        ++*s;
88
+        --*len;
89
+    }
90
+
91
+// brute force, try NSCalendarDate first    
92
+// then NSDecimalNumber Number 
93
+// finally stay as NSString
94
+#if TRY_VALIANTLY_TO_CONVERT
95
+    if( isdigit( *memo))
96
+    {
97
+        if( value = [NSDecimalNumber decimalNumberWithString:string])
98
+            return( value);
99
+    }
100
+    
101
+    if( value = [NSCalendarDate dateWithString:string])
102
+        return( value);
103
+#endif
104
+        
105
+    return( string);
106
+}
107
+
108
+
109
+static int   _parse_key_value_into_dictionary( char **s, unsigned int *len, NSMutableDictionary *dictionary)
110
+{
111
+    id   key;
112
+    id   value;
113
+    
114
+    
115
+    key = _parse_value( s, len);
116
+    if( ! key)
117
+        return( -1);
118
+    
119
+    if( skip_white( s, len))
120
+    {
121
+       NSLog( @"Malformed key value pair, only key %@ present", key);
122
+       return( -2);
123
+    }
124
+
125
+    if( **s != '=')
126
+    {
127
+       NSLog( @"Malformed key value pair, = missing after key %@", key);
128
+       return( -3);
129
+    }
130
+    
131
+    ++*s;
132
+    --*len;
133
+    
134
+    if( skip_white( s, len))
135
+    {
136
+       NSLog( @"Malformed key value pair, missing value after key %@", key);
137
+       return( -4);
138
+    }
139
+   
140
+    value = _parse_object( s, len);
141
+    if( ! value)
142
+    {
143
+       NSLog( @"Malformed key value pair, missing value after key %@", key);
144
+       return( -4);
145
+    }
146
+    [dictionary setObject:value
147
+                   forKey:key];
148
+                   
149
+    return( 0);
150
+}
151
+
152
+
153
+static id   _parse_array( char **s, unsigned int *len)
154
+{
155
+    NSMutableArray   *array;
156
+    id               parsed;
157
+    
158
+    array = [NSMutableArray array];
159
+    while( *len)
160
+    {
161
+        if( skip_white( s, len))
162
+            return( nil);
163
+    
164
+        if( **s == ',')
165
+        {
166
+           ++*s;
167
+           --*len;
168
+           continue;
169
+        }
170
+
171
+        if( **s == ')')
172
+        {
173
+           ++*s;
174
+           --*len;
175
+           return( array);
176
+        }
177
+
178
+        parsed = _parse_object( s, len);
179
+        if( ! parsed)
180
+            break;
181
+        [array addObject:parsed];
182
+    }
183
+    NSLog( @"Array truncated");
184
+    return( nil);
185
+}
186
+
187
+
188
+static id   _parse_dictionary( char **s, unsigned int *len)
189
+{
190
+    NSMutableDictionary   *dictionary;
191
+    
192
+    dictionary = [NSMutableDictionary dictionary];
193
+    while( *len)
194
+    {
195
+        if( skip_white( s, len))
196
+            break;
197
+                
198
+        if( **s == ';')
199
+        {
200
+           ++*s;
201
+           --*len;
202
+           continue;
203
+        }
204
+        
205
+        if( **s == '}')
206
+        {
207
+           ++*s;
208
+           --*len;
209
+           return( dictionary);
210
+        }
211
+        
212
+        if( _parse_key_value_into_dictionary( s, len, dictionary) < 0)
213
+            return( nil);
214
+    }
215
+    NSLog( @"Dictionary truncated");
216
+    return( nil);
217
+}
218
+
219
+
220
+static id  _parse_object( char **s, unsigned int *len)
221
+{
222
+    if( skip_white( s, len))
223
+        return( nil);
224
+        
225
+    switch( **s)
226
+    {
227
+    case '{' :
228
+        ++*s;
229
+        --*len;
230
+        return( _parse_dictionary( s, len));
231
+
232
+    case '(' :
233
+        ++*s;
234
+        --*len;
235
+        return( _parse_array( s, len));
236
+    }
237
+    return( _parse_value( s, len));
238
+}
239
+
240
+
241
+static id  parse_old_plist( NSData *data)
242
+{
243
+   char         *s;
244
+   NSUInteger   len;
245
+   
246
+   s   = (char *) [data bytes];
247
+   len = [data length];
248
+   return( _parse_object( &s, &len));
249
+}
250
+
251
+
252
++ (id) mullePropertyListFromData:(NSData *) data
253
+                mutabilityOption:(NSPropertyListMutabilityOptions) option 
254
+                          format:(NSPropertyListFormat *) format
255
+                errorDescription:(NSString **) error
256
+{
257
+   id   list;
258
+   
259
+   list = [NSPropertyListSerialization propertyListFromData:data
260
+                                           mutabilityOption:option 
261
+                                                     format:format 
262
+                                           errorDescription:error];
263
+   if( ! list)
264
+   {
265
+      // can only do immutable containers
266
+      if( option == NSPropertyListImmutable)
267
+      {
268
+         list = parse_old_plist( data);
269
+         if( list)
270
+            *format = NSPropertyListOpenStepFormat;
271
+      }
272
+      // fall through, if this is nil then Foundation
273
+      // will provide the error 
274
+   }
275
+   return( list);
276
+}
277
+
278
+@end
0 279
new file mode 100644
... ...
@@ -0,0 +1,319 @@
0
+#import "NSPropertyListSerialization+MullePlistWriter.h"
1
+
2
+
3
+NSString *MullePlistWriterException = @"MullePlistWriterException";
4
+
5
+
6
+@interface NSObject ( MullePlistWriter)
7
+
8
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
9
+                          indent:(NSData *) indent;
10
+
11
+@end
12
+
13
+
14
+@implementation NSObject ( MullePlistWriter)
15
+
16
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
17
+                          indent:(NSData *) indent
18
+{
19
+   [NSException raise:MullePlistWriterException
20
+               format:@"Objects of class %@ can't be saved in a plist", isa];
21
+}
22
+
23
+@end
24
+
25
+
26
+/*
27
+ *
28
+ *
29
+ */
30
+
31
+@interface NSData ( MullePlistWriter)
32
+
33
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
34
+                          indent:(NSData *) indent;
35
+@end
36
+
37
+
38
+static inline char	hexit( unsigned char c)
39
+{
40
+   return( c > 10 ? 'A' - 10 + c : '0' + c);
41
+}
42
+
43
+
44
+@implementation NSData ( MullePlistWriter)
45
+
46
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
47
+                          indent:(NSData *) indent
48
+{
49
+   NSMutableData   *buffer;
50
+   char            *hex;
51
+   unsigned char   *s;
52
+   NSUInteger      len;
53
+   NSUInteger      i;
54
+   
55
+   len    = [self length];
56
+   buffer = [NSMutableData dataWithLength:len * 3 + 3];
57
+   
58
+   hex = (char *) [buffer bytes];
59
+   s   = (unsigned char *) [self bytes];
60
+
61
+   *hex++ = '<';
62
+   i = 0;
63
+   while( len)
64
+   {
65
+      *hex++ = hexit( *s >> 4);
66
+      *hex++ = hexit( *s & 0xF);
67
+      if( ! (++i & 0x7))
68
+         *hex++ = ' ';
69
+      s++;
70
+   }
71
+   *hex++ = '>';
72
+   
73
+   len = (char *) hex - (char *) [buffer bytes];
74
+   [buffer setLength:len];
75
+   [data appendBytes:buffer
76
+              length:len];
77
+}
78
+
79
+@end
80
+
81
+/*
82
+ *
83
+ *
84
+ */
85
+
86
+@interface NSNumber ( MullePlistWriter)
87
+
88
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
89
+                          indent:(NSData *) indent;
90
+@end
91
+
92
+
93
+@implementation NSNumber ( MullePlistWriter)
94
+
95
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
96
+                          indent:(NSData *) indent
97
+{
98
+   char  *s;
99
+
100
+   s = (char *) [[self descriptionWithLocale:nil] UTF8String];
101
+   [data appendBytes:s
102
+              length:strlen( s)];
103
+}
104
+
105
+@end
106
+
107
+/*
108
+ *
109
+ *
110
+ */
111
+
112
+
113
+@interface NSString ( MullePlistWriter)
114
+
115
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
116
+                          indent:(NSData *) indent;
117
+
118
+@end
119
+
120
+
121
+@implementation NSString ( MullePlistWriter)
122
+
123
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
124
+                          indent:(NSData *) indent
125
+{
126
+   char      *s;
127
+   BOOL      quoted;
128
+   NSArray   *components;
129
+   NSString  *quotedSelf;
130
+   
131
+   quoted  = [self rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length;
132
+   quoted |= [self rangeOfCharacterFromSet:[NSCharacterSet punctuationCharacterSet]].length;
133
+   quoted |= [self length] == 0;
134
+      
135
+   components = [self componentsSeparatedByString:@"\""];
136
+   quotedSelf = [components componentsJoinedByString:@"\\\""];
137
+   quoted |= [components count] > 1;
138
+      
139
+   if( quoted)
140
+      [data appendBytes:"\""
141
+                 length:1];
142
+
143
+
144
+   s = (char *) [quotedSelf UTF8String];
145
+   [data appendBytes:s
146
+              length:strlen( s)];
147
+   if( quoted)
148
+      [data appendBytes:"\""
149
+                 length:1];
150
+}
151
+
152
+@end
153
+
154
+/*
155
+ *
156
+ *
157
+ */
158
+
159
+
160
+@interface NSArray ( MullePlistWriter)
161
+
162
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
163
+                          indent:(NSData *) indent;
164
+
165
+@end
166
+
167
+
168
+@implementation NSArray ( MullePlistWriter)
169
+
170
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
171
+                          indent:(NSData *) indent
172
+{
173
+   NSMutableData   *indent2;
174
+   unsigned int    i, n;
175
+
176
+   [data appendBytes:"("
177
+              length:1];
178
+   n = [self count];
179
+   if( n)
180
+   {
181
+      [data appendBytes:"\n"
182
+                 length:1];
183
+      indent2 = [indent mutableCopy];
184
+      [indent2 appendBytes:"   "
185
+                    length:3];
186
+      for( i = 0; i < n; i++)
187
+      {
188
+         if( i > 0)
189
+            [data appendBytes:",\n"
190
+                       length:2];
191
+         [data appendData:indent2];
192
+         [[self objectAtIndex:i] mullePlistWriteIntoData:data
193
+                                                  indent:indent2];
194
+      }
195
+      [data appendBytes:"\n"
196
+                 length:1];
197
+      [data appendData:indent];
198
+   }
199
+   [data appendBytes:")"
200
+              length:1];
201
+}
202
+
203
+
204
+@end
205
+
206
+/*
207
+ *
208
+ *
209
+ */
210
+
211
+
212
+@interface NSDictionary ( MullePlistWriter)
213
+
214
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
215
+                          indent:(NSData *) indent;
216
+
217
+@end
218
+
219
+
220
+@implementation NSDictionary ( MullePlistWriter)
221
+
222
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
223
+                          indent:(NSData *) indent
224
+{
225
+   NSArray         *keys;
226
+   id              key;
227
+   id              value;
228
+   NSMutableData   *indent2;
229
+   unsigned int    i, n;
230
+
231
+   [data appendBytes:"{"
232
+              length:1];
233
+   keys = [self allKeys];  // sort'em ?
234
+   n    = [keys count];
235
+
236
+   if( n)
237
+   {
238
+      [data appendBytes:"\n"
239
+                 length:1];
240
+
241
+//      keys    = [keys sortedArrayUsingSelector:@selector( compare:)];
242
+      indent2 = [indent mutableCopy];
243
+      [indent2 appendBytes:"   "
244
+                    length:3];
245
+
246
+      for( i = 0; i < n; i++)
247
+      {
248
+         key   = [keys objectAtIndex:i];
249
+         value = [self objectForKey:key];
250
+
251
+         [data appendData:indent2];
252
+         [key mullePlistWriteIntoData:data
253
+                               indent:nil];
254
+         [data appendBytes:" = "
255
+                    length:3];
256
+         [value mullePlistWriteIntoData:data
257
+                                 indent:indent2];
258
+         [data appendBytes:";\n"
259
+                    length:2];
260
+
261
+      }
262
+      [data appendData:indent];
263
+   }
264
+   [data appendBytes:"}"
265
+              length:1];
266
+}
267
+
268
+@end
269
+
270
+
271
+
272
+@implementation NSPropertyListSerialization ( MullePlistWriter)
273
+
274
+
275
++ (NSData *) plistDataFromObject:(id) obj
276
+                errorDescription:(NSString **) error
277
+{
278
+   NSMutableData   *data;
279
+   
280
+   if( ! obj)
281
+   {
282
+      *error = @"plist is nil";
283
+      return( nil);
284
+   }
285
+   
286
+   data = [NSMutableData dataWithCapacity:0x1000];
287
+   [obj mullePlistWriteIntoData:data
288
+                         indent:[NSData data]];
289
+   if( ! [data length])
290
+   {
291
+      *error = @"Some objects were not plist compatible";
292
+      return( nil);
293
+   }
294
+
295
+#if 0   
296
+   [data appendBytes:""  // trailin zero
297
+              length:1];
298
+#endif   
299
+   return( data);
300
+}
301
+
302
+
303
++ (id) mulleDataFromPropertyList:(id) plist
304
+                          format:(NSPropertyListFormat) format
305
+                errorDescription:(NSString **) error
306
+{
307
+   if( format != NSPropertyListOpenStepFormat)
308
+      return( [self dataFromPropertyList:plist
309
+                                  format:format
310
+                         errorDescription:error]);
311
+   
312
+   return( [self plistDataFromObject:plist
313
+                    errorDescription:error]);
314
+}
315
+
316
+
317
+@end
318
+