public
Rubygem
Description: Ruby osx/plist extension for reading/writing property lists
Clone URL: git://github.com/kballard/osx-plist.git
Search Repo:
Add new tests for <6 characters
Fix loading < 6 characters
Fix a leak of the property list ref
kballard (author)
Fri Aug 12 18:34:41 -0700 2005
commit  9df33ffdef33a043729f6e707d68c413359c099f
tree    88669893688cbd6ff5a4b5a25ba45614d361c2d1
parent  3f0fb2bbbbb3a251d3c7f542865f6b8fa084a796
...
67
68
69
 
 
70
71
72
...
99
100
101
102
103
104
105
106
107
108
...
107
108
109
110
 
 
 
111
 
112
113
114
115
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
118
119
120
121
122
 
123
124
125
126
127
128
129
130
...
393
394
395
396
397
398
399
400
 
 
 
 
 
401
402
403
404
405
406
 
 
 
 
 
407
408
409
410
 
 
411
412
413
 
 
414
415
416
417
 
 
 
418
419
420
 
 
421
422
423
...
431
432
433
434
 
435
436
437
...
441
442
443
444
 
445
446
447
...
465
466
467
 
468
...
67
68
69
70
71
72
73
74
...
101
102
103
 
104
105
106
107
108
109
...
108
109
110
 
111
112
113
114
115
116
 
 
 
 
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
421
422
423
 
 
 
 
 
424
425
426
427
428
429
 
 
 
 
 
430
431
432
433
434
435
436
 
 
437
438
439
 
 
440
441
442
 
 
 
443
444
445
446
 
 
447
448
449
450
451
...
459
460
461
 
462
463
464
465
...
469
470
471
 
472
473
474
475
...
493
494
495
496
497
0
@@ -67,6 +67,8 @@
0
 static VALUE id_binary;
0
 static VALUE id_openstep;
0
 
0
+static VALUE id_blob;
0
+
0
 VALUE convertPropertyListRef(CFPropertyListRef plist);
0
 VALUE convertStringRef(CFStringRef plist);
0
 VALUE convertDictionaryRef(CFDictionaryRef plist);
0
@@ -99,7 +101,6 @@
0
   int count = rb_scan_args(argc, argv, "11", &io, &retFormat);
0
   if (count < 2) retFormat = Qfalse;
0
   VALUE buffer;
0
- //if (RTEST(rb_obj_is_kind_of(io, rb_cIO))) {
0
   if (RTEST(rb_respond_to(io, id_read))) {
0
     // Read from IO
0
     buffer = rb_funcall(io, id_read, 0);
0
0
0
0
@@ -107,19 +108,46 @@
0
     StringValue(io);
0
     buffer = io;
0
   }
0
- CFReadStreamRef readStream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8*)RSTRING(buffer)->ptr, RSTRING(buffer)->len, kCFAllocatorNull);
0
+ // For some reason, the CFReadStream version doesn't work with input < 6 characters
0
+ // but the CFDataRef version doesn't return format
0
+ // So lets use the CFDataRef version unless format is requested
0
   CFStringRef error = NULL;
0
+ CFPropertyListRef plist;
0
   CFPropertyListFormat format;
0
- CFReadStreamOpen(readStream);
0
- CFPropertyListRef plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListImmutable, &format, &error);
0
- CFReadStreamClose(readStream);
0
- CFRelease(readStream);
0
+ if (RTEST(retFormat)) {
0
+ // Format was requested
0
+ // now just in case, if the input is < 6 characters, we will pad it out with newlines
0
+ // we could do this in all cases, but I don't think it will work with binary
0
+ // even though binary shouldn't be < 6 characters
0
+ UInt8 *bytes;
0
+ int len;
0
+ if (RSTRING(buffer)->len < 6) {
0
+ bytes = ALLOC_N(UInt8, 6);
0
+ memset(bytes, '\n', 6);
0
+ MEMCPY(bytes, RSTRING(buffer)->ptr, UInt8, RSTRING(buffer)->len);
0
+ len = 6;
0
+ } else {
0
+ bytes = (UInt8 *)RSTRING(buffer)->ptr;
0
+ len = RSTRING(buffer)->len;
0
+ }
0
+ CFReadStreamRef readStream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, len, kCFAllocatorNull);
0
+ CFReadStreamOpen(readStream);
0
+ plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, readStream, 0, kCFPropertyListImmutable, &format, &error);
0
+ CFReadStreamClose(readStream);
0
+ CFRelease(readStream);
0
+ } else {
0
+ // Format wasn't requested
0
+ CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8*)RSTRING(buffer)->ptr, RSTRING(buffer)->len, kCFAllocatorNull);
0
+ plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data, kCFPropertyListImmutable, &error);
0
+ CFRelease(data);
0
+ }
0
   if (error) {
0
     raiseError(error);
0
     CFRelease(error);
0
     return Qnil;
0
   }
0
   VALUE obj = convertPropertyListRef(plist);
0
+ CFRelease(plist);
0
   if (RTEST(retFormat)) {
0
     VALUE ary = rb_ary_new();
0
     rb_ary_push(ary, obj);
0
0
0
0
0
0
@@ -393,31 +421,31 @@
0
   CFNumberType type;
0
   switch (TYPE(obj)) {
0
     case T_FLOAT: {
0
- double num = NUM2DBL(obj);
0
- valuePtr = &num;
0
- type = kCFNumberDoubleType;
0
- break;
0
- }
0
+ double num = NUM2DBL(obj);
0
+ valuePtr = &num;
0
+ type = kCFNumberDoubleType;
0
+ break;
0
+ }
0
     case T_FIXNUM: {
0
- int num = NUM2INT(obj);
0
- valuePtr = &num;
0
- type = kCFNumberIntType;
0
- break;
0
- }
0
+ int num = NUM2INT(obj);
0
+ valuePtr = &num;
0
+ type = kCFNumberIntType;
0
+ break;
0
+ }
0
     case T_BIGNUM: {
0
 #ifdef NUM2LL
0
- long long num = NUM2LL(obj);
0
- type = kCFNumberLongLongType;
0
+ long long num = NUM2LL(obj);
0
+ type = kCFNumberLongLongType;
0
 #else
0
- long num = NUM2LONG(obj);
0
- type = kCFNumberLongType;
0
+ long num = NUM2LONG(obj);
0
+ type = kCFNumberLongType;
0
 #endif
0
- valuePtr = &num;
0
- break;
0
- }
0
+ valuePtr = &num;
0
+ break;
0
+ }
0
     default:
0
- rb_raise(rb_eStandardError, "ERROR: Wrong object type passed to convertNumber");
0
- return NULL;
0
+ rb_raise(rb_eStandardError, "ERROR: Wrong object type passed to convertNumber");
0
+ return NULL;
0
   }
0
   CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, type, valuePtr);
0
   return number;
0
@@ -431,7 +459,7 @@
0
 
0
 
0
 VALUE str_blob(VALUE self) {
0
- VALUE blob = rb_iv_get(self, "@blob");
0
+ VALUE blob = rb_attr_get(self, id_blob);
0
   if (NIL_P(blob)) {
0
     return Qfalse;
0
   } else {
0
@@ -441,7 +469,7 @@
0
 
0
 VALUE str_setBlob(VALUE self, VALUE b) {
0
   if (TYPE(b) == T_TRUE || TYPE(b) == T_FALSE) {
0
- return rb_iv_set(self, "@blob", b);
0
+ return rb_ivar_set(self, id_blob, b);
0
   } else {
0
     rb_raise(rb_eArgError, "Argument 1 must be true or false");
0
     return Qnil;
0
@@ -465,5 +493,6 @@
0
   id_xml = rb_intern("xml1");
0
   id_binary = rb_intern("binary1");
0
   id_openstep = rb_intern("openstep");
0
+ id_blob = rb_intern("@blob");
0
 }
...
10
11
12
 
 
 
 
 
 
 
 
 
 
 
13
14
15
...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0
@@ -10,6 +10,17 @@
0
     plist, format = PropertyList.load("{foo = bar; }", true)
0
     assert_equal( { "foo" => "bar" }, plist )
0
     assert_equal( :openstep, format )
0
+
0
+ # make sure sources < 6 characters work
0
+ plist = PropertyList.load("foo")
0
+ assert_equal( "foo", plist )
0
+
0
+ # make sure it works with format too
0
+ plist, format = PropertyList.load("foo", true)
0
+ assert_equal( "foo", plist )
0
+ assert_equal( :openstep, format )
0
+
0
+ assert_raise(PropertyListError) { PropertyList.load("") }
0
   end
0
 
0
   def setup_hash

Comments

    No one has commented yet.